0

I have an MSI that installs some services. I changed the name for one of them and updated references in Wix files.

It works fine when I just install it as fresh MSI. However, when there is an upgrade scenario (where MSI is installed with the old service name and I try to install this new MSI that has one of the service name changed), I get the following error:

ERROR

Any hints here? I am just renaming in .wxs files. Do I have to uninstall the old one with the existing component id and name the new one with new component id?

Currently, using the old component id with a new name.

SOME PART OF OLD CODE:

<Directory Id="dirxxx" Name="oldname">
                <!-- oldname service-->
              <Component Id="cmpOldNameService" Guid="bbb"
                  SharedDllRefCount="no" KeyPath="no" NeverOverwrite="no" Permanent="no" Transitive="no"
                  Win64="no" Location="either">
              <RemoveFile Id="ccc" On="uninstall" Name="z.dll"/>
              <File Id="ccc" KeyPath="no" Source="$(var.xSource)\OldNameService\a.dll"/>
              <File Id="ddd" KeyPath="no" Source="$(var.xSource)\OldNameService\b.dll"/>
              <File Id="eee" KeyPath="no" Source="$(var.xSource)\OldNameService\c.dll"/>
              <File Id="fff" KeyPath="no" Source="$(var.xSource)\OldNameService\d.dll"/>
              <File Id="ggg" KeyPath="no" Source="$(var.xSource)\OldNameService\e.dll"/>
              <File Id="hhh" KeyPath="no" Source="$(var.xSource)\OldNameService\f.dll"/>
              <File Id="iii" KeyPath="yes" Source="$(var.xSource)\OldNameService\g.exe"/>
              <File Id="jjj" KeyPath="no" Source="$(var.xSource)\OldNameService\h.dll"/>
              <File Id="kkk" KeyPath="no" Source="$(var.xSource)\OldNameService\i.dll"/>
              <ServiceInstall Id="OldNameService" DisplayName="OldName Service" Name="NewName"
                ErrorControl="normal" Start="auto" Type="ownProcess" Vital="yes" Description="OldName Service">
                <ServiceConfig DelayedAutoStart="yes" OnInstall="yes" OnReinstall="yes"/>
              </ServiceInstall>

              <ServiceControl Id="OldNameServiceControl" Name="NewName"
                Start="install" Stop="uninstall" Remove="uninstall" Wait="no"/>

            </Component>

              <Component Id="lll" Guid="mmm" NeverOverwrite="yes">
                <File Id="nnn" KeyPath="yes" Source="$(var.xSource)\OldNameService\OldName.exe.config"/>
                <util:XmlFile Id="UpdateOldNamelogFileName"
                              File="[#nnn]"
                              Action="setValue"
                              ElementPath="/configuration/appSettings/add[\[]@key='logFile'[\]]/@value"
                              Value="[ooo]oldname_YYYYMM.log" />
              </Component>

REPLACED WITH NEW CODE:

<Directory Id="dirxxx" Name="newname">
                <!-- newname service-->
              <Component Id="cmpNewNameService" Guid="bbb"
                  SharedDllRefCount="no" KeyPath="no" NeverOverwrite="no" Permanent="no" Transitive="no"
                  Win64="no" Location="either">
              <RemoveFile Id="ccc" On="uninstall" Name="z.dll"/>
              <File Id="ccc" KeyPath="no" Source="$(var.xSource)\NewNameService\a.dll"/>
              <File Id="ddd" KeyPath="no" Source="$(var.xSource)\NewNameService\b.dll"/>
              <File Id="eee" KeyPath="no" Source="$(var.xSource)\NewNameService\c.dll"/>
              <File Id="fff" KeyPath="no" Source="$(var.xSource)\NewNameService\d.dll"/>
              <File Id="ggg" KeyPath="no" Source="$(var.xSource)\NewNameService\e.dll"/>
              <File Id="hhh" KeyPath="no" Source="$(var.xSource)\NewNameService\f.dll"/>
              <File Id="iii" KeyPath="yes" Source="$(var.xSource)\NewNameService\g.exe"/>
              <File Id="jjj" KeyPath="no" Source="$(var.xSource)\NewNameService\h.dll"/>
              <File Id="kkk" KeyPath="no" Source="$(var.xSource)\NewNameService\i.dll"/>
              <ServiceInstall Id="NewNameService" DisplayName="NewName Service" Name="NewName"
                ErrorControl="normal" Start="auto" Type="ownProcess" Vital="yes" Description="New Name Service">
                <ServiceConfig DelayedAutoStart="yes" OnInstall="yes" OnReinstall="yes"/>
              </ServiceInstall>

              <ServiceControl Id="NewNameServiceControl" Name="NewName"
                Start="install" Stop="uninstall" Remove="uninstall" Wait="no"/>

            </Component>

              <Component Id="lll" Guid="mmm" NeverOverwrite="yes">
                <File Id="nnn" KeyPath="yes" Source="$(var.xSource)\NewNameService\NewName.exe.config"/>
                <util:XmlFile Id="UpdateNewNamelogFileName"
                              File="[#nnn]"
                              Action="setValue"
                              ElementPath="/configuration/appSettings/add[\[]@key='logFile'[\]]/@value"
                              Value="[ooo]newservice_YYYYMM.log" />
              </Component>
Atihska
  • 4,803
  • 10
  • 56
  • 98
  • Can you rename the service file in the update setup? If you can, try to both rename the service file AND give it a new component GUID. – Stein Åsmul Aug 16 '17 at 00:34
  • Major upgrade or minor upgrade? – Christopher Painter Aug 16 '17 at 10:15
  • @SteinÅsmul edited my post and added code. – Atihska Aug 16 '17 at 21:44
  • @ChristopherPainter Haven't tagged anything specific. This is the only change that I want to make. Not sure if this will come under major or minor. – Atihska Aug 16 '17 at 21:45
  • Implement a major upgrade and you'll be fine. This is basically one of those "undocumented" component rules. https://blogs.msdn.microsoft.com/windows_installer_team/2007/03/07/arbitrary-labels-used-as-primary-keys-must-not-be-changed-between-versions/ – Christopher Painter Aug 16 '17 at 22:18

2 Answers2

2

This became too long to add as a comment, I am adding this as an answer though it perhaps doesn't answer things for you:

  • The most obvious "error" or at least non-standard issue is that you have a lot of binaries in a single component. This is not best practice (very bad practice in fact).
  • Before you do anything else, please split that component of yours and create one component per file. I always use a single file per component, even for non-binaries, but best practice states that you should always use a separate component for binaries. In essence it is a requirement for proper deployment.
  • To keep it very short: if you keep multiple files in the same component, only one of them is a key file. If that file has not had its version number incremented (for binaries), all the other files won't be updated either - even if their versions are incremented. Only the key file determines whether the component is installed or not. And a component is only installed as a whole or not at all.
  • Things work in a similar fashion for non-versioned files, but then it is not the version that is checked, but whether or not the file has been modified or not. If the file on disk has been modified, then the component is not installed. Read more in the MSDN article File Versioning Rules. You can also check this Symantec article on the same issue. And the answer to this question is worth a read (along with the comment from Chris Painter): File Versioning Rules When Neither Components Has a Key File
  • If you have a "live version" of your application I would use a major upgrade with RemoveExistingProducts scheduled early in the InstallExecuteSequence. In plain English this means that you will fully uninstall the previous version before the new version is installed. This should eliminate any errors following from your component creation error or whatever other errors are there. I didn't read it too thoroughly, but this answer (the first one) seems to be an OK explanation of how to schedule your major upgrade: How to get WiX major upgrade working?. Or go straight for the source and check the WiX 3 documentation for how to implement a major upgrade, and just for good measure I include this link: How to implement WiX installer upgrade?
  • In addition to all this I want to suggest that you "simplify" your WiX XML as explained in this answer: Syntax for guids in WIX?. The less attributes you define, the easier it is to read the file content, and the less errors can hide (and upgrades in XML format might be easier later).
  • Please try this "component fix" and major upgrade tweak first to see if this resolves your problems. And try the source simplification too.
Stein Åsmul
  • 39,960
  • 25
  • 91
  • 164
  • I figured the problem but haven't found the solution. So I have to uninstall the old service and all its components and then install new service. – Atihska Aug 21 '17 at 23:15
  • What should be my ServiceControl and ServiceInstall element? Are both of them needed for old service that is already installed? Also, do I need to add RemoveFolder to every component in that directory? – Atihska Aug 21 '17 at 23:16
  • I would schedule a major upgrade where you uninstall the old version completely before installing the new version. This involves running RemoveExistingProducts before InstallInitialize in the InstallExecuteSequence. I would put the ServiceControl and the ServiceInstall elements in the component that holds your main service executable. I am assuming you have converted your setup to use one component per file? – Stein Åsmul Aug 23 '17 at 02:01
0

So I was able to solve my problem here. I wanted to do a minor upgrade and added Account property in ServiceInstall as Network Service.

<ServiceInstall Id="Service1" DisplayName="My Service" Name="MyService"
                    ErrorControl="normal" Start="auto" Type="ownProcess" Vital="yes" Description="My Service" Account="NT Authority\NetworkService">
Atihska
  • 4,803
  • 10
  • 56
  • 98