Using wix to install a windows service that may already be installed - wix

I'm using WiX 3.1.1 to install an exe and a service. Sometimes, the MSI install fails with a fairly generic error:
Error 1923. Service 'MyService' (MyService) could not be installed.
Verify that you have sufficient privileges to install system services.
Experimentally, this appears to be because the service already exists, and my xml uses Vital="yes"
I would like to have the MSI ensure the service is installed, but accept (or repair) it if it's already present. It sounds like I should set Vital="no", will this cause it to ignore other errors? Is there a way to limit what kind of errors are ignored? Is there a best practice I'm missing?
For reference, a redacted snippet of my xml:
<Component Id="REDACTED" Guid="{REDACTED}" Win64="yes">
<File
Id="filB754EE270009E240193A8279D1529A43"
Name="myservice.exe"
KeyPath="yes"
DiskId="1"
Source="SourceDir\File\filB754EE270009E240193A8279D1529A43" />
<ServiceControl
Id="MyService"
Name="MyService"
Start="install"
Stop="both"
Remove="uninstall"
Wait="no" />
<ServiceInstall
Id="MyService"
Name="MyService"
Type="ownProcess"
Start="auto"
ErrorControl="normal"
Vital="yes"
Account="[SERVICEACCOUNT]"
Arguments="svc -config "C:\Program Files\MyService\conf\service.flags""
Description="My Service">
<ServiceConfig
ServiceName="MyService"
FirstFailureActionType="restart"
SecondFailureActionType="restart"
ThirdFailureActionType="restart"
ResetPeriodInDays="1"
RestartServiceDelayInSeconds="5"
xmlns="http://schemas.microsoft.com/wix/UtilExtension" />
</ServiceInstall>
</Component>

Related

Wix: Installer slow because file in use

I use wix toolset to install an ASP.NET Core application as a windows service. When doing a major upgrade, the installer can take very long (5 mins) while it usually is a couple of seconds. This is because the InstallValidate action gives errors because files are in use by the service, I noticed that if I stop the service before starting the installer, it always runs smoothly. I use the following code to install and start/stop the service: (this is generated using heat)
<Component Id="ApiEndpoint.exe" Guid="*">
<File Id="ApiEndpoint.exe" KeyPath="yes" Source="$(var.publishDir)\ApiEndpoint.exe" />
<wix:ServiceInstall Id="ApiEndpointInstall" DisplayName="ApiEndpoint" Name="ApiEndpoint" ErrorControl="normal" Start="auto" Type="ownProcess" Vital="yes" xmlns:wix="http://schemas.microsoft.com/wix/2006/wi" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
<util:ServiceConfig RestartServiceDelayInSeconds="60" ResetPeriodInDay="1" FirstFailureActionType="restart" SecondFailureActionType="restart" ThirdFailureActionType="restart" />
</wix:ServiceInstall>
<wix:ServiceControl Id="ApiEndpointControl" Name="ApiEndpoint" Start="install" Stop="both" Remove="uninstall" xmlns:wix="http://schemas.microsoft.com/wix/2006/wi" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension" />
</Component>
Shouldn't the files in use by the ApiEndpoint be excluded because the service will be stopped anyway? Is there a way I can stop the service before the InstallValidate, I tried this with a custom action, but this wasn't possible because no admin privileges are present at that point.
I also tried to ignore the exe file from heat and make a component for it myself, like below, this results in the same issue.
<Fragment xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
<ComponentGroup Id="ExeComponents" Directory="INSTALLFOLDER">
<Component Win64="yes" Id="ExeComponent" Guid="*">
<File Id="ExecFile" Source="$(exeSource)" KeyPath="yes" />
<ServiceInstall Id="ApiEndpointInstall" DisplayName="ApiEndpoint" Name="ApiEndpoint" ErrorControl="normal" Start="auto" Type="ownProcess" Vital="yes">
<util:ServiceConfig RestartServiceDelayInSeconds='60' ResetPeriodInDays='1' FirstFailureActionType='restart' SecondFailureActionType='restart' ThirdFailureActionType='restart' />
<util:PermissionEx
User="Everyone"
GenericAll="yes"
ServiceChangeConfig="yes"
ServiceEnumerateDependents="yes"
ChangePermission="yes"
ServiceInterrogate="yes"
ServicePauseContinue="yes"
ServiceQueryConfig="yes"
ServiceQueryStatus="yes"
ServiceStart="yes"
ServiceStop="yes" />
</ServiceInstall>
<ServiceControl Id="ApiEndpointControl" Name="ApiEndpoint" Start="install" Stop="both" Remove="uninstall" />
</Component>
</ComponentGroup>
</Fragment>
I'm very new at wix so I'm not sure if I'm missing something obvious or if this is just a limit of Wix.
I can see that the service stops eventually when the files are being copied, but it just seems like it is stopped either too late, or the installer should ignore the files in use by the service that will be stopped anyway.

Wixtoolset - lock appears after installing

I made an msi with wixtoolset and I give permissions to the installed files to all users with the code below. The problem is that after installing, all the files on the screen appear with a lock on them. I still have permission to access them but I would like to avoid the lock thing.
My Wix version is 3.5
I know the problem is with the permissions I give because when I remove them from the instakker, the lock does not appear.
<DirectoryRef Id="INSTALLFOLDERSERVICE">
<!-- SERVICE FILES -->
<!-- Create a single component which is the TestService.exe file -->
<Component Id="SERVICE" GUID="*">
<!-- Remove all files from the INSTALLFOLDER on uninstall -->
<RemoveFile Id="ALLFILES" Name="*.*" On="both" />
<!-- Tell WiX to install the Service -->
<ServiceInstall Id="ServiceInstaller"
Type="ownProcess"
Name="SERVICEtoINSTALL"
DisplayName="$(var.Name)"
Description=""
Start="auto"
ErrorControl="normal" />
<!-- Tell WiX to start the Service -->
<ServiceControl Id="StartService" Start="install" Stop="both" Remove="uninstall" Name="SERVICEtoINSTALL" Wait="yes" />
<CreateFolder>
<Permission User="Everyone" GenericAll="yes" />
</CreateFolder>
</Component>
the code compiles perfectlly. I need that permissions to manage the files from other app but I would like to avoid the lock thing.
You can see it here;
https://drive.google.com/open?id=1Z6zYEt444DjOXe2ODP60q2X00Xpq5bkZ
Thank you!!
I found the solution! The problem was that I was giving permissions to folder of the shortcut on Desktop, removing that permission tag solved my problem!

Wix File property with user selected directory

I am trying to install a windows service using wix but I can't seem to point the file for the service to the user selected install directory.
<Component Id="MyServiceInstaller_ServiceControl" Guid="B72CAA3F-F2DB-48D2-90DD-061209AB2CE5" Directory="INSTALLDIR">
<CreateFolder />
<File Id='MyServiceEXE' Name='MyService.exe' DiskId='1' Source='[INSTALLDIR]MyService.exe' KeyPath='yes'/>
<ServiceInstall Id="MyServiceInstaller_ServiceInstall"
Type="ownProcess"
Vital="yes"
Name="My Service"
DisplayName="My Service"
Description="This will make windows services great again!"
Start="auto"
Account="NT AUTHORITY\LocalService"
ErrorControl="ignore"
Interactive="no" />
<ServiceControl Id="MyServiceInstaller_ServiceInstall"
Name="My Service"
Stop="both"
Remove="uninstall"
Wait="yes" />
</Component>
The issue seems to be when I use any [PROPERTY] directory I get the following error.
error LGHT0103 : The system cannot find the file
'[INSTALLDIR]MyService.exe'.
How do I tell Wix to use the installation folder the user selected as the path for the service?
File/#Source points to the file in your build environment. Component/#Directory tells Windows Installer where the file should be installed. That controls the file used to install and control the service.

How to wait for a file being installed to GAC before installing a service with wix

I'm using Wix to create my application installer and using it to install an assembly in the GAC and it works fine.
My issue is when I'm setting the assembly property 'copy local=false' and I'm executing the installation, then my services is not being installed cause it can't find this dll in the local folder and it's not being installed to GAC yet.
If I'll install another component from the EXE installation and will verify that the DLL is in the GAC I will be able then to install the service.
I'm using Paraffin.exe to go all over my application directory and generate a wix file and also using Mold file to add component not from this directory.
<DirectoryRef Id="Manager">
<Component Id="NlogGACRegisterComponent" Guid="1B224CD1-6EE8-46D3-9335-A84B7D8FB87B">
<File Id="NlogDLL" Name="Nlog.DLL" Source="..\Logging\Nlog.DLL" KeyPath="yes" Vital="yes" Assembly=".net"/>
</Component>
<Component Id="ManagerServiceComponent" Guid="EA31E161-4331-4A82-8F2B-7E26F62C96D6">
<File Id="StateManagerServiceEXE" Name="ManagerHostService.exe" DiskId="1" Source="..\ManagerHostService.exe" KeyPath="yes" Vital="yes" />
<ServiceInstall Id="ServiceInstaller" Type="ownProcess" Name="ManagerHostService" DisplayName="Manager Service" Description="Manager Service" Start="auto" Account="[SERVICEACCOUNT]" Password="[SERVICEPASSWORD]" ErrorControl="normal">
<util:PermissionEx User="Everyone" GenericAll="yes" ServiceChangeConfig="yes" ServiceEnumerateDependents="yes" ChangePermission="yes" ServiceInterrogate="yes" ServicePauseContinue="yes" ServiceQueryConfig="yes" ServiceQueryStatus="yes" ServiceStart="yes" ServiceStop="yes" />
</ServiceInstall>
<ServiceControl Id="StartService" Start="install" Name="ManagerHostService" Stop="both" Remove="uninstall" Wait="yes" />
</Component>
</DirectoryRef>
This in the Mold file which responsible to install the DLL to GAC and then the service.
How can I make sure it first install the DLL's and then the service?
All files and Dlls ARE installed by the time that services are started. Look in your MSI file with Orca at the InstallExecuteSequence (or look in a verbose log) and you'll see that InstallServices and StartServices are after InstallFiles.
The issue is that assemblies aren't installed and available in the GAC until InstallFinalize, this is described here:
https://msdn.microsoft.com/en-us/library/aa370063(v=vs.85).aspx
where it says "This means you cannot use the ServiceControl Table to start the service, instead you must use a custom action that is sequenced after InstallFinalize." which is what you'll need to do.

ServiceInstall does not successfully start mywindowsservice

I am trying to create a WIX installer that will install a Windows Service. For the Windows service, I create a service exactly how it's outlined http://tech.pro/tutorial/895/creating-a-simple-windows-service-in-csharp.
In my wxs installer file, I have the following markup specified -
<Component Id="MyCompanyWindowsServiceComponent" Guid="*">
<File Id="MyCompanyWindowsServiceFile" Name="SimpleWindowsService.exe" DiskId="1"
Source="..\SimpleWindowsService\bin\debug\SimpleWindowsService.exe"/>
<ServiceInstall Id="MyCompanyServiceInstall" Type="ownProcess" Vital="yes"
Name="MyCompany:MyProduct"
DisplayName="MyCompany:MyProduct"
Description="MyCompany Windows Service"
Start="auto"
Account="LocalSystem"
ErrorControl="critical"
Interactive="yes"/>
<ServiceControl Id="StartService"
Start="install"
Stop="both"
Remove="uninstall"
Name="MyCompany:MyProduct"
Wait="no"/>
</Component>
and I have the component referenced like -
<Feature Id="Complete" Level="1">
::
<ComponentRef Id="MyCompanyWindowsServiceComponent"/>
</Feature>
When I finally run my installer, I see the file has been copied to the right location but the service itself hasn't been started.
What am I missing?
Regards