We install our software with Wix. Our setup also installs a Windows service. To allow users to change the login information for the Windows service we only want to install the service on first installation and only delete it on uninstall. For upgrades we manually stop the service so the files can be upgraded.
We have this working, but recently we found that on some machines the Windows service gets uninstalled during UnpublishFeatures:
This if from a failed upgrade log:
Action 13:41:38: UnpublishFeatures. Unpublishing Product Features
MSI (s) (D8:EC) [13:41:38:346]: Executing op: FeatureUnpublish(Feature=Main,,Absent=2,Component=
UnpublishFeatures: Feature: Main
MSI (s) (D8:EC) [13:41:38:346]: Note: 1: 1402 2: UNKNOWN\Installer\Features\84B659030632F794E93A7CB19A87DB8E 3: 2
MSI (s) (D8:EC) [13:41:38:346]: Executing op: ActionStart(Name=StopServices,Description=Stopping services,Template=Service: [1])
Action 13:41:38: StopServices. Stopping services
MSI (s) (D8:EC) [13:41:38:362]: Executing op: ProgressTotal(Total=1,Type=1,ByteEquivalent=1300000)
MSI (s) (D8:EC) [13:41:38:362]: Executing op: ServiceControl(,Name=RidderIQWebApi,Action=2,Wait=1,)
StopServices: Service: Ridder iQ Web API
MSI (s) (D8:EC) [13:41:38:393]: Executing op: ActionStart(Name=DeleteServices,Description=Deleting services,Template=Service: [1])
Action 13:41:38: DeleteServices. Deleting services
MSI (s) (D8:EC) [13:41:38:393]: Executing op: ProgressTotal(Total=1,Type=1,ByteEquivalent=1300000)
MSI (s) (D8:EC) [13:41:38:393]: Executing op: ServiceControl(,Name=RidderIQWebApi,Action=8,Wait=1,)
DeleteServices: Service: Ridder iQ Web API
This if from a log from a successfull upgrade:
Action 11:53:24: UnpublishFeatures. Unpublishing Product Features
MSI (s) (CC:3C) [11:53:24:976]: Executing op: FeatureUnpublish(Feature=Main,,Absent=2,Component=
UnpublishFeatures: Feature: Main
MSI (s) (CC:3C) [11:53:24:977]: Note: 1: 1402 2: UNKNOWN\Installer\Features\84B659030632F794E93A7CB19A87DB8E 3: 2
MSI (s) (CC:3C) [11:53:24:978]: Executing op: ActionStart(Name=RemoveFiles,Description=Removing files,Template=File: [1], Directory: [9])
Action 11:53:24: RemoveFiles. Removing files
As you can see Windows Installer skips the StopServices/DeleteServices actions and starts removing the files. Because the service is deleted on UnpublishFeatures later during the setup it attempts to configure the service, but fails because it's no longer installed:
MSI (s) (D8:68) [13:42:34:772]: Executing op: CustomActionSchedule(Action=ExecServiceConfig,ActionType=3073,Source=BinaryData,Target=ExecServiceConfig,CustomActionData=)
MSI (s) (D8:90) [13:42:34:772]: Invoking remote custom action. DLL: C:\Windows\Installer\MSI170B.tmp, Entrypoint: ExecServiceConfig
ExecServiceConfig: Error 0x80070424: Service 'RidderIQWebApi' does not exist on this system.
ExecServiceConfig: Error 0x80070424: Failed to get service: RidderIQWebApi
CustomAction ExecServiceConfig returned actual error code 1603 (note this may not be 100% accurate if translation happened inside sandbox)
Action ended 13:42:35: InstallFinalize. Return value 3.
My guess is that this happens because the action for the component is different for both upgrades, for the failed upgrade these are the component actions:
MSI (s) (D8:68) [13:41:26:400]: Component: cmp.SR.SDKWebAPI.Service.exe; Installed: Absent; Request: Local; Action: Local
MSI (s) (D8:EC) [13:41:36:400]: Component: cmp.SR.SDKWebAPI.Service.exe; Installed: Local; Request: Absent; Action: Absent
For the successfull upgrade these are the component actions:
MSI (s) (CC:44) [11:53:17:386]: Component: cmp.SR.SDKWebAPI.Service.exe; Installed: Absent; Request: Local; Action: Local
MSI (s) (CC:3C) [11:53:22:850]: Component: cmp.SR.SDKWebAPI.Service.exe; Installed: Local; Request: Absent; Action: FileAbsent
As you can see the action for the failed upgrade is Absent, and for the successfull upgrade is FileAbsent. From what I've read the FileAbsent means that the feature is reinstalled and Absent means the feature will be removed.
My question is how are the actions for components determined, and why is it on one machine Absent and on another machine FileAbsent. And is there a way to fix this?
The component if configured like this:
<Component Id="cmp.SR.SDKWebAPI.Service.exe" Guid="">
<File Id="fil.SDKWebAPI.Service.exe" Source="SDKWebAPI.Service.exe" KeyPath="yes" />
<File Id="fil.SDKWebAPI.Service.exe.config" Source="SDKWebAPI.Service.exe.config" KeyPath="no" />
<ServiceInstall Id="SDKWebAPI.Service.exe.Installer"
Type="ownProcess"
Name="RidderIQWebApi"
DisplayName="Ridder iQ Web API"
Description="Ridder iQ Web API service"
Start="auto"
Account="LocalSystem"
ErrorControl="ignore">
<util:ServiceConfig FirstFailureActionType="restart"
SecondFailureActionType="restart"
ThirdFailureActionType="restart"
RestartServiceDelayInSeconds="60"
ResetPeriodInDays="0" />
</ServiceInstall>
</Component>