Wix: Installer slow because file in use - wix

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.

Related

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

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>

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.

Condition property failure in WIX failing entire MSI job

I am using WIX to create MSI installers for C# services. The MSI does 3 jobs :
a) Copy solution file from bin to a particular location.
b) Create a folder where the service writes it's logs.
c) install the service on the machine if it previously does not exist.
The want these to execute in the similar order. But, when the condition to check if the service is installed fails the previous step does not seem to be executing, i.e, copying and creating steps fail too.
Here is the snippet of the code.
<Directory Id="TARGETDIR" Name="SourceDir">
<!--Creating folder hierarchy for storing project solution files; reference defined in fragments-->
<Directory Id="ProgramFilesFolder" Name="PFiles"/>
<!--Creating folder hierarchy for storing logs; reference defined in fragments-->
<Directory Id="LOGS" Name="Logs"/>
</Directory>
<InstallExecuteSequence>
<LaunchConditions After='AppSearch' />
<Custom Action='CMDInstallService' Before='InstallFinalize'></Custom>
</InstallExecuteSequence>
<Property Id="MYSERVICE">
<RegistrySearch Id="SERVICE_CHECK" Root="HKLM" Name="Install" Type="raw"
Key="SYSTEM\CurrentControlSet\services\Service"/>
</Property>
<Condition Message="Service is already installed on your system">
<![CDATA[Installed OR MYSERVICE]]>
</Condition>
<CustomAction
Id='CMDInstallService' Directory='PROJECT_INSTALL' Execute='deferred' Impersonate='no'
ExeCommand='[SystemFolder]cmd.exe /K "C:\Windows\Microsoft.NET\Framework\v4.0.30319\installutil.exe Service.exe"'
Return ='check'/>
This will not work because the files and folder are not committed before InstallFinalize. To install a service, you should use the following command:
<Component Id="Component_WinService" Directory="Directory_WindowsService" Guid="*">
<File Id="File_WindowsService" KeyPath="yes"
Source="WindowsService.exe" />
<ServiceInstall Id="ServiceInstall_WindowsService"
Type="ownProcess"
Vital="yes"
Name="My Windows service"
Description="Windows service."
Start="auto"
Account="LocalSystem"
ErrorControl="ignore"
Interactive="no"
/>
<ServiceControl Id="ServiceControl_WindowsService"
Start="install"
Stop="both"
Remove="uninstall"
Name="My Windows Service"
Wait="no"
/>
</Component>

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