Search code examples
installationwixwindows-services

Don't override the service account when upgrading a service using WiX toolset


I am trying to setup a WiX installer that install a windows service and handles upgrades and updates.

The installer works like a charm, the user installs the service under the LocalSystem account then a service engineer has to assign a domain account to that service.

Here is my service installer component:

  <Component Id="my_exe_Component">
    <File Id="Myexe" Source="$(var.Myproject.TargetPath)" KeyPath="yes" />
    <ServiceInstall Id="my_exe" Type="ownProcess" Vital="no" Name="NME" DisplayName="My intaller" Description="My installer description" Start="auto" Account="LocalSystem" ErrorControl="ignore" Interactive="no">
      <util:ServiceConfig
        FirstFailureActionType="restart"
        SecondFailureActionType="restart"
        ThirdFailureActionType="restart"
        RestartServiceDelayInSeconds="0"
        ResetPeriodInDays="1"/>
    </ServiceInstall>
    <ServiceControl Id="my_exe" Stop="both" Remove="uninstall" Name="NME" Wait="yes" />
  </Component>

When I perform an upgrade to the installer, the account set to the service get overwritten back to the LocalSystem account, how do I persist the account set to my service when performing an upgrade?

My upgrade clause is set like so:

 <MajorUpgrade AllowSameVersionUpgrades="yes" AllowDowngrades="no" DowngradeErrorMessage="A newer version of [ProductName] is already installed." Schedule="afterInstallExecute" />

Any help would be appreciated.


Solution

  • This is a classic source of truth problem. MSI wants to be the source of truth and doesn't have anything in it's code to account for this scenario. It thinks the service should be LocalSystem and so it wants to fix it. ( This isn't just upgrades ... a repair will do the same thing. )

    So, what to do?

    Option A:

    Bring username /password configuration into the MSI. UI work, credential validation and encryption of the creds persisting it on the machine somewhere so that subsequent transactions can decrypt and reuse the credentials.

    Note: Risk. The creds can be reverse engineered.. I got news though... so can windows LSA secrets and Application Pool Identities and such.

    Option B:

    Use custom actions to create the service. This way you can do logic to not touch the service during subsequent transactions.

    Option C:

    Put conditional expressions on CreateServices standard action to only apply during first time installation and not major upgrades.

    Risk: If you ever change anything else about the service it won't get deployed by an upgrade because it's been bypassed. Also this is for all services in your MSI not just this one.

    Option D:

    Embrace running as a built in service account and use active directory permissions to grant that computer object rights to whatever it connects to.

    Option E:

    If the user applies creds after install, then they can simply do it again after upgrade. They can deal with it.