Windows Service installed by Wix - windows-services

I'm using WiX 3.6 to create an installer for a windows service. I have the solution building and am able to install the service on my development machine and the service starts just like I wanted.
The problem arises when I copy the msi (either Build or Release) to a Windows Server 2003 R2 machine that the service will run on.
I am able to install the service, but when I try to start the service I get an error
"Service failed to start. Verify that you have sufficient privileges
to start system service."
Now I am able to install and start other services that I created so I now I that I do have permissions to the server. Below is my service install element.
My question is, what I am I missing that the service starts on the development machine and not the server?
<File Id="CopyService.exe" Name="CopyService.exe" Source="..\CopyService\bin\$(var.CopyService.Configuration)\CopyService.exe" Vital="yes" KeyPath="yes" DiskId="1"/>
<File Id="App.config" Name="CopyService.exe.config" Source="..\CopyService\bin\$(var.CopyService.Configuration)\CopyService.exe.config" Vital="yes" KeyPath="no" DiskId="1"/>
<ServiceInstall
Id="ServiceInstaller"
Type="ownProcess"
Vital="yes"
Name="ACSIAccountingReports"
DisplayName="ACSI Accounting Reports"
Description="Service copies accounting reports from NetForum into an ACSI network folder."
Start="auto"
Account="LocalSystem"
ErrorControl="ignore"
Interactive="no">
</ServiceInstall>
<ServiceControl Id="StartService" Name="ACSIAccountingReports" Start="install" Wait="yes" />
<ServiceControl Id="StopService" Name="ACSIAccountingReports" Stop="both" Wait="yes" Remove="uninstall" />

The error message you are seeing is the default error message from the Windows Installer for all service install failures. It's not terribly helpful. To debug the real issue, try to start your service again while the error dialog is up. It is likely you'll get a more detailed error message about why your service is not starting. If you still get nothing, try using a tool like depends.exe or fuslogvw (to turn on NETFX assembly load failures) to see if you service executable has some missing dependencies.
Remember, GAC'd files are not completed until the very end of the install. Therefore, your service cannot depend on GAC'd files and start the service during the install.

Related

.Net Core windows service not installing in a docker container

I am facing a very peculiar issue. I have a .net core windows service (XYZ) whose installer (XYZ.msi) is created using Wix. I am trying to install this service in a container. The service gets installed, then windows tries to register it as a service, the service times out giving me the following "information" in System Eventlogs The XYZ Service (XYZ) service failed to start due to the following error: %%1053 A timeout was reached (30000 milliseconds) while waiting for the XYZ service (XYZ) service to connect., and then the service gets uninstalled which is expected.
Further when I check the Application event logs I get these
Product: XYZ -- Error 1920. Service 'XYZ' (XYZ) failed to start. Verify that you have sufficient privileges to start system services.
Windows Installer installed the product. Product Name: XYZ. Product Version: 0.0.0.0. Product Language: 1033. Manufacturer: .... Installation success or error status: 1603.
So in order to understand these error codes I referred to Error Code 1603 and few other links on Error 1920, but since these are pretty generic, these links were of no use.
The same service is working fine locally and on a different server.
The folder inside the container where XYZ.msi resides has these privileges
Path : Microsoft.PowerShell.Core\FileSystem::C:\app
Owner : NT AUTHORITY\SYSTEM
Group : NT AUTHORITY\SYSTEM
Access : BUILTIN\Administrators Allow FullControl
BUILTIN\Administrators Allow 268435456
NT AUTHORITY\SYSTEM Allow FullControl
NT AUTHORITY\SYSTEM Allow 268435456
NT AUTHORITY\Authenticated Users Allow Modify, Synchronize
NT AUTHORITY\Authenticated Users Allow -536805376
BUILTIN\Users Allow ReadAndExecute, Synchronize
BUILTIN\Users Allow -1610612736
Audit :
Sddl : O:SYG:SYD:(A;ID;FA;;;BA)(A;OICIIOID;GA;;;BA)(A;ID;FA;;;SY)(A;OICIIOID;GA;;;SY)(A;ID;0x1301bf;;;AU)(A;OICIIOID;SDGXGWGR;;;AU)(A;ID;0x1200a9;;;BU)(A;OICIIOID;GXGR;;;BU)
Also I am assuming that all the installation happen with ContainerAdministrator account inside the container.
Now I am not able to figure out what the problem is, how to troubleshoot it further and if its a privileges issue what privileges do I need to set. Any help in this regard would be appreciated. Thanks !
EDIT: The dockerFile looks like this
FROM mcr.microsoft.com/windows/servercore:ltsc2019-amd64
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
WORKDIR /app
COPY [".","."]
RUN ["powershell.exe", "./install.cmd"]
WiX .wxs code
<Fragment>
<ComponentGroup Id="ServiceComponents" Directory="APPLICATIONFOLDER">
<Component Id="ServiceComponent" Guid="649E5964-126A-4DF5-95CF-CE7C2474E981">
<File Id="xyz.exe" KeyPath="yes" Vital="yes" DiskId="1" Source="..\xyz\bin\$(var.Platform)\$(var.Configuration)\netcoreapp3.1\win-x64\xyz.exe"/>
<ServiceInstall
Id="ServiceInstaller"
Type="ownProcess"
Vital="yes"
Name="xyz"
DisplayName="$(var.ProductName)"
Description="$(var.Description)"
Start="auto"
Account="NT AUTHORITY\LocalService"
ErrorControl="normal" Interactive="no">
<ServiceConfig DelayedAutoStart="yes" OnInstall="yes" OnReinstall="yes" />
<util:ServiceConfig FirstFailureActionType="restart" SecondFailureActionType="restart" ThirdFailureActionType="none" ResetPeriodInDays="1" RestartServiceDelayInSeconds="0" />
</ServiceInstall>
<ServiceControl
Id="ServiceController"
Name="xyz"
Start="install"
Stop="both"
Remove="both"
Wait="yes" />
</Component>
</ComponentGroup>
</Fragment>
I've personally never attempted to install an MSI inside a container. The containers I've worked with (mostly linux based) the container simple would call the EXE as a console app and it's not actually a service per say. I'll assume from what you write that it's somehow possible to install an MSI inside of a windows container.
With that said, the 1920 error simply means the service didn't start. The 'verify you have admin' has always been a misnomer. To troubleshoot in windows I usually pause the installer right there and try to run the EXE manually to see if I get any errors to the console. Typically this will be a message saying .NET (Core) or some dependency isn't installed. If the EXE actually starts and you have some exception down the road then this will take additional debugging.
I'm not sure how you hijack a windows container but you'll need to do something similar to debug/profile the issue. Basically it works on one machine and not your container because your docker image doesn't have something that the other machine does have and your code doesn't like it.
I would first try and find the root cause of the problem by installing the MSI with verbose logging enabled. Here you can find an example of how to do that. The logfile should give more details regarding what happened (maybe you have some failing custom actions in your installer and the infamous 'value 3' in the log file).
I would also try and modify the wxs file so that installation does not start the service (by removing ServiceControl Start="install" and replacing ServiceInstall Start="auto" with ServiceInstall Start="demand"). With this modification installation of MSI should probably succeed. Are you then able to start the xyz.exe (directly, not as a service)? If no, the problem is not in the installation, but in the executable. Are you able to start the service manually after those changes?
Although I am still investigating the behavior of .net core windows service and has started another thread here to take the SO community's view on this, it appears that the problem was with the way the service was implemented. It's a strange behavior but if I do not use Worker Template that comes with .net core 3 and instead create the service like it was done in .net core 2.1 using ServiceBase and IHostingLifetime it works fine in all the environments.

Nuget package restore error in Docker Compose build

I am getting nugget restore error while building using docker-compose behind proxy. I have set proxy in docker for windows. Nuget restore works for command line dotnet restore and visual studio debug, but not using docker-compose.
:\Program Files\dotnet\sdk\2.1.104\NuGet.targets(104,5): error : Unable to load the service index for source https://api.nuget.org/v3/index.json. [C:\src\WebApp.sln]
:\Program Files\dotnet\sdk\2.1.104\NuGet.targets(104,5): error : An error occurred while sending the request. [C:\src\WebApp.sln]
:\Program Files\dotnet\sdk\2.1.104\NuGet.targets(104,5): error : A connection with the server could not be established [C:\src\WebApp.sln]
ERROR: Service 'idenityapi' failed to build: The command 'powershell -Command $ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue'; dotnet restore -nowarn:msb3202,nu1503' r
turned a non-zero code: 1
SOLVED:
It turns out to be a networking issue. I am behind a corporate firewall at work that leverages TLS packet inspection to break apart SSL traffic. The build process while debugging runs as "me" on my local machine, however, the release build (docker-compose) actually pulls down a aspnetcore-build docker image, copies your code to the docker container, then runs dotnet restore to get fresh nuget packages for your docker image. These actions can be found in the Docker File in your project. This "dotnet restore" inside the container, runs under a different security context, and therefore was getting hung up. We traced the network traffic which was hard for me to get to because of how docker networking works. Fiddler was not catching the traffic. Using wireshark, we were able to catch it from a device level and see the drop. The reason it continued to fail from my home network was due to the configuration with our hypervisor & networking.
RESOLUTIONS:
Add a firewall rule for https://api.nuget.org/v3/index.json (Preferred)
OR
Build the image from VSTS in the cloud
OR
Build from a different network.
PS4 please post back if you are able to resolve this the same way? Having spent 3 days on this, I'm curious about your status.
When I ran into this issue with dotnet restore adding the corporate cert file fixed the issue. (May or may not be the same in your case?). Before RUN dotnet restore I added to the container's certificate store i.e.
ADD your-proxy-certificate-file.crt /usr/local/share/ca-certificates/your-proxy-certificate-file.crt
RUN update-ca-certificates
In theory, if dotnet restore works on your local machine, there's no reason you shouldn't be able to configure your container to work (without firewall rules or changing network!). You essentially need to configure the container to work behind your proxy with the same setup as your local machine.
You can check network adapter indexes. docker uses last in the list. if it's disconnected - you will not be able to restore packages as image is not able to get to the internet to download ones.
check network interface list:
❯ Get-NetIPInterface -AddressFamily IPv4 | Sort-Object -Property InterfaceMetric -Descending
Change index for LAN (ex. move it above Wi-Fi):
❯ Set-NetIPInterface -InterfaceAlias 'Local Area Connection* 1' -InterfaceMetric 100
I had similar problem when corporate SSL interception blocked nuget package restore. The error was slightly different though: "The remote certificate is invalid because of errors in the certificate chain: PartialChain"
The following solution helped me:
Export Windows certificate that is used to connect to SSL proxy in PEM format;
Add following lines to Dockerfile:
COPY ["exported_windows_cert_path_and_name.cer", "/usr/local/share/ca-certificates/cert_name.cer"]
RUN openssl x509 -inform PEM -in '/usr/local/share/ca-certificates/cert_name.cer' -out '/usr/local/share/ca-certificates/cert_name.crt'
RUN update-ca-certificates
It can also be used DER certificate type instead of PEM.
I too am getting this same error now. I've been working on it for 2 days to no avail. I've determined that it doesn't seem to be a network related issue. I can load the same project on my home laptop and it builds. I brought my work laptop home it doesn't build. That points me to my work laptop having something amis.
I had fiddler open, and it never tries to hit the URL. I'm running short on ideas at this point for what to do.
I tried creating another "template" project from a simple API/website... it builds fine... I add Nuget Packages and it suddenly fails.
My error message is exactly the same as PS4's.
Steps to reproduce this are easy.
1) Create a new .NET Core Web Project
2) Enable Docker support (either through new project wizard or Add context menu)
3) Select Release Mode
4) Hit Play/Debug/Go button.
One thing that PS4 and I both share is that both of us have "dotnet sdk 2.1.104"
I tried to change my network connection as well...recreated all the images and containers but it did not work then I tried
--disable-parallel and it worked.
Note: I am using docker-compose command to run all of my microservices and I entered --disable-parallel in my Docker file right after dotnet restore command
I was experiencing the same error during docker builds but mine was due to a bad nexus server that was simply unable to keep up with the number of requests being generated. The solutions listed above of --disable-parallel and <add key='maxHttpRequestsPerSource' value='16' /> do work but they cause the build to be incredibly slow.
The real solution wasn't available until package-source-mapping became available. https://devblogs.microsoft.com/nuget/introducing-package-source-mapping/
This allowed me to direct only the necessary connections to my custom nexus server and the rest to nuget.org which has no problem dealing with the connection count.
This is pulled from the article.
<!-- This is where installed packages will be stored locally. -->
<config>
<add key="globalPackagesFolder" value="globalPackagesFolder" />
</config>
<!-- Define my package sources, nuget.org and contoso.com. -->
<!-- `clear` ensures no additional sources are inherited from another config file. -->
<packageSources>
<clear />
<!-- `key` can be any identifier for your source. -->
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
<add key="contoso.com" value="https://contoso.com/packages/" />
</packageSources>
<!-- Define mappings by adding package ID patterns beneath the target source. -->
<!-- Contoso.* packages will be restored from contoso.com, everything else from nuget.org. -->
<packageSourceMapping>
<!-- key value for <packageSource> should match key values from <packageSources> element -->
<packageSource key="nuget.org">
<package pattern="*" />
</packageSource>
<packageSource key="contoso.com">
<package pattern="Contoso.*" />
</packageSource>
</packageSourceMapping>
Worked for me like a charm! Now i can build at normal build speeds and i don't overload the nexus server that is only hosting 1-2 proprietary packages.

How to stop NewRelic from running on my local machine?

I am using the New Relic monitoring service with the .NET agent. It runs on the production server.
However, I also get statistics from my local machine when I am testing/developing the application. I used the New Relic Server Monitor Configuration tool to stop the service, and also disabled it with services.msc. But I still see my local machine in the "servers" section when I check my application on newrelic.com.
What should I do (either in my application or with my machine) to stop this?
The Windows Server Monitor is a different application from the .Net Agent. You will need to disable the .Net Agent in order for your development system to stop sending data to your application. If you don't want to have the .Net Agent run at all on your development system you can alter the newrelic.config file in %ALLUSERSPROFILE%\New Relic\.NET Agent to disable it by changing the following:
<configuration xmlns="urn:newrelic-config" agentEnabled="true">
to
<configuration xmlns="urn:newrelic-config" agentEnabled="false">
This has the advantage of being set globally, but if you want to turn it on and off per application you can add the following in the web application's web.config:
<appSettings>
<add key="NewRelic.AgentEnabled" value="false"/>
</appSettings>
I have multiple Azure service configurations (ServiceConfiguration.(Release/Local).cscfg. I simply removed the licensekey from the Local configuration. And uninstalled the two agents on my Windows machine (via Change or Remove a Program).
When I ran the project again locally, it didn't report, so all is good ;)

Using port 80 with IIS Express inside of VS2010

I've got an app that I am trying to run on my dev system under IIS Express from VS2010 that I need to use port 80 for, but I can't get it to work. I've looking up information talking about port 80 being reserved.
http://learn.iis.net/page.aspx/1005/handling-url-binding-failures-in-iis-express/
But even after doing that I still get an error from vs2010 that says
"Unable to launch the IIS Express Web server. Port '80' is in use."
I don't know what else to try. I've used Process Hacker to track down port 80 and it seems to be used by System running on process ID 4, which is the NT Kernel and System process. I don't know if that would prevent me from using the port though. I thought maybe that was a result of http.sys holding that port so nothing else could use it?
I did managed to get IIS Express to run on port 80 by modifying the default binding of the C:\Users\[MyUser]\Documents\IISExpress\config\applicationhost.config file, and while I can start IIS Express manually this way, VS then gets an error because a binding already exists on that port. So I change it back to 8080, create the virtual directory using the button within VS2010 (which I'm guessing is the same as entering a site binding) but I still get an error when I go to debug the application. Is there something hardcoded in VS2010 that won't let it start IIS Express on port 80?
UPDATE & FIX: Ok, so I found a few more things to check and I did resolve my problem but not completely. One post suggested making sure I did not have SQL reporting services installed as it can monitor on port 80, I used to have it installed but not anymore and was not the problem I was encountering. I did however realize that I have WebDeploy installed. It was bundled with the VS2010 SP1 bundle from the Web Platform Installer. This is fine as I do want the client tools from WebDeploy, but it also installed the agent on my system which was monitoring on port 80. I went to my list of services and stopped the Web Deploy Agent Service. Soon as I did this I can now use port 80 for IIS Express from within VS2010.
New Issue related to running on port 80 in IIS Express
However my application is an MVC3 App, and I've run into a problem because the MVC3 isn't capturing my request at all, so It's not firing my controller actions or anything like that, but a txt file in the root of my app can be reached so I know it's my site that IIS Express is serving up. Anyone have any issues running an MVC3 (I don't know if it's exclusive to MVC3 or not) in IIS Express on port 80?
Just posting my own answer for this problem so I can mark the question as answered.
Check http://learn.iis.net/page.aspx/1005/handling-url-binding-failures-in-iis-express/
Disable the Web Deploy Agent service if you have it installed.
in my case i solved the issue by stop "SQL Server Reporting Services"
you can find it in
control panel -> sevices
THANK YOU very much for you discovering of the 'Web Deploy Agent' service! This is something that only recently got turned on as I had all this working perfectly and just today installed the updated version of IIS Express, and ran into the exact same problem with port 80. So now that I have turned off the Web Deploy agent, my system works correctly again.
As for ASP.NET MVC3, that works great for me on port 80 and port 443. It was quite a bit of work to bind both those ports so that IIS Express was able to use them as a normal user (most of it from the link you posted above), and to install the SSL certificate we use. I manually created all the entries in my applicationhost.config file to get this working, and the appropriate sites section is below:
<sites>
<site name="PHP: A Main" id="2144116512">
<application path="/">
<virtualDirectory path="/" physicalPath="C:\var\www\amain\www" />
<virtualDirectory path="/images" physicalPath="C:\var\www\images" />
</application>
<application path="/admin">
<virtualDirectory path="/" physicalPath="C:\var\www\amain\www\admin" />
</application>
<bindings>
<binding protocol="http" bindingInformation="*:80:test.amainhobbies.com" />
<binding protocol="https" bindingInformation="*:443:test.amainhobbies.com" />
</bindings>
</site>
<siteDefaults>
<logFile logFormat="W3C" directory="%IIS_USER_HOME%\Logs" />
<traceFailedRequestsLogging directory="%IIS_USER_HOME%\TraceLogFiles" enabled="true" maxLogFileSizeKB="1024" />
</siteDefaults>
<applicationDefaults applicationPool="Clr4IntegratedAppPool" />
<virtualDirectoryDefaults allowSubDirConfig="true" />
</sites>
Note that my site is a combined PHP and ASP.NET MVC3 site, as we are in the process of re-writing the entire thing to run on ASP.NET MVC3, so most of the site is still PHP but lots of new stuff is now running ASP.NET MVC3, and that stuff works for me.
Does your IIS Express work properly with MVC3 outside of Visual Studio, or is the MVC3 stuff just not working at all?
I didn't have the Web Deploy Agent installed but ran into this issue. You can also fix this by running this command to find out which application or service is using the port and then trace it down in Task manager.
netstat -o -n -a | findstr 0.0:80
Then open Task manager, go to Processes, click the checkbox "Show processes for all users" and then click the View menu and Go to the Columns, add the PID column.
Match the Process ID from the netstat command to the PID in task manager and you will find the service or application that's using the port.
That solution helped me.
On Windows 7 or Windows Vista, from an elevated command prompt, run the following command:
console
netsh http add urlacl url=http://localhost:80/ user=everyone
This command will allow any user's application (including your own IIS Express instances) to run using port 80 without requiring administrative privileges. To limit this access to yourself, replace "everyone" with your Windows identity.
Taken from that source -> https://learn.microsoft.com/en-us/iis/extensions/using-iis-express/handling-url-binding-failures-in-iis-express

WIX ServiceInstall - setting the service to run under the NetworkService account

I am trying to create a WIX installer to install my windows service to run under the NetworkService account and getting an Insufficient Priviledges error during the installation.
I found this post where someone seems to be experiencing the same problem but no real solution was offered:
http://n2.nabble.com/Re-WiX-users-Digest-Vol-40-Issue-129-td3782055.html
I'm sure someone must have acheived this previously and wondered if they'd be kind enough to share a code snippet?
NOTE: The answer below is only relevant on the older builds of WIX and Windows at the time the question was raised. The current version of the WIX service credentials will work if you set the native "NT AUTHORITY" domain and "NetworkService" account (no space necessary now).
Original Answer:
The correct identity name is "NT Authority\Network Service" not "NT Authority\NetworkService". A space is required then it works.
Funny that the default "LocalSystem" works directly with WIX 3.5, but for other well known accounts you have to prefix with "NT Authority...", for example "LocalService" does not work either when used directly.
i.e. fix this with:
Account='NT Authority\Network Service'
It seems a few remnants of a previously failed install were preventing me from removing and reinstalling with Account="NT Authority\NetworkService". All is well in the universe again.
I had the following snippet working under Windows 8.1 FR, and Windows 2012R2 ENU. But using NT AUTHORITY\NETWORK SERVICE failed with the insufficied privileges error.
So, at least under recent systems you must use NT AUTHORITY\NETWORKSERVICE as documented in MSDN.
<ServiceInstall Id="xserviceInstall" Name="$(var.xServiceid)"
DisplayName="$(var.xServiceid)"
Description="x service" Start="auto" Type="ownProcess"
ErrorControl="ignore"
Account="NT AUTHORITY\NETWORKSERVICE"
Arguments="-w -N" Vital="yes" />
I used customAction to find the user credentials are correct or not.
If user credentials are matches the account in the machine they want to install,I will allow them to proceed to next dialog(UI) other wise I will show another Dialog indicating the user that account not found.

Resources