Reputation: 20768
I am struggling to get MajorUpgrade, ServiceControl, .config files to work nicely together. After my other question, I'm now kinda having the opposite problem again.
Before, the files weren't being overwritten because the AssemblyFileVersions were static so I fixed that. 1) Now, even with Schedule="afterInstallExecute"
my KeyPath='yes'
.config file is still being overwritten even though the existing file modified date is different than the file creation date and it is set as a KeyPath. I'm currently having to overwrite the .config file and restart the service after the install.
2) And even if I fix that, I still have a problem of avoiding a reboot. If I say Schedule="afterInstallInitialize"
then I believe the .config file will certainly be removed along with the service too early. If I say Schedule="afterInstallExecute"
then the service isn't stopped and after the install a reboot is necessary. (That's right, right?) Stopping the service manually prior to the install let's me avoid the reboot. Adding a net stop
custom action could work to replace the ServiceControl
I guess, but getting all the conditions right seems complex.
3) As a bonus, I'd like to NOT remove the service at all during an upgrade. Can I just stop the service, replace the binary, and start the service again? That will avoid re-entering the service account credentials for an upgrade. But of course it still needs to install on a first install and uninstall on a feature removal.
Here's the meat of it (which is also bundled later, in case that somehow matters):
<MajorUpgrade DowngradeErrorMessage="A newer version is already installed."
Schedule="afterInstallExecute" />
<ComponentGroup Id="ServiceCG">
<Component Id="Service" Guid='*' Win64='yes' Directory='INSTALLDIR'>
<File Id='ServiceEXE' Source='$(var.root)Service.exe' />
<ServiceInstall Id="ServiceInstall"
Name="MyService"
DisplayName="My Server"
Type="ownProcess"
Start="auto"
ErrorControl="normal"
Description="My Server Service"
Interactive="no"
Account="[...]"
Password="[...]" />
<ServiceControl Id="StopService" Name="MyService" Start="install"
Stop="uninstall" Wait="yes" Remove="both" />
<util:User Id="UpdateServiceAccountLogonAsService" UpdateIfExists="yes"
CreateUser="no" Name="[SERVICEACCOUNTFULL]"
LogonAsService="yes"/>
</Component>
<Component Id="ServiceConfig" Guid='*' Win64='yes' Directory='INSTALLDIR'>
<File Id='FileServiceConfig' KeyPath='yes'
Source='$(var.root)Service.exe.config' />
</Component>
</ComponentGroup>
Related but unanswered:
WiX version 3.8.1128.0
Upvotes: 11
Views: 2463
Reputation: 42126
EDIT: it seems this explanation of the same issue, or on the same topic at least, might be easier to understand: Msiexec: automatic rollback to previous version on installation failure
You are banging your head against several core MSI usage problems here.
Component referencing: refers to the GUIDs assigned to MSI components and how they must match one, and only one (absolute) path at all times through all upgrades. See a better discussion of this with a couple of examples here: Change my component GUID in wix?
I didn't mention the option of setting the MSI components installing services to permanent to prevent their removal on uninstall for the simple reason that this isn't good practice at all. Then files and registration will remain on final uninstall, and you need a custom action to clean up. Very bad practice and bound to cause lots of extra work and problems with dangling component references.
Upvotes: 5
Reputation: 55571
The file create/mod rule only applies to install/reinstall a component. It doesn't prevent the component from being uninstalled. Your major upgrade is scheduled very early which means the previous version is completely uninstalled and then then the new version is installed. This is why your file is overwriting when you don't expect it to. Schedule RemoveExistingProducts later to avoid this problem.
Set your Stop attribute to both install and uninstall. Those two changes should solve your problems.
Upvotes: 4