Billy ONeal
Billy ONeal

Reputation: 106530

Dealing with Changed Upgrade Code in WiX, where old installer allowed both per-user and per-machine

I have a product that used to ship with a .vdproj installer. In the most recent version, I shipped a beta with a completely redone installer using WiX (as part of the move to Visual Studio 2012, which no longer supports .vdproj). Unfortunately, at the time I didn't know that the upgrade code was supposed to be consistent across copies, and already shipped one beta installer with a different upgrade code.

I would like my installer to automatically remove previous versions built with the .vdproj installer, as well as the version that was shipped as a beta copy. This is where I've gotten so far:

<Product Id="{A4CBA9F9-D86B-400C-BD23-996B4367931A}" Name="Foo Viewer" Language="1033" Version="6.0.1.0" Manufacturer="Foo Corporation" UpgradeCode="43e024b8-b3ea-40a3-a854-2af83f207f0f">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />

<MediaTemplate EmbedCab="yes" />

<Feature Id="FOOVIEWERFeature" Title="Foo Viewer" Level="1" Description="The Foo Viewer GUI and CLI binaries." AllowAdvertise="no" Absent="disallow" Display="expand">
<!-- Stuff -->
</Feature>

<PropertyRef Id="NETFRAMEWORK40CLIENT" />
<Condition Message="Foo Viewer requires the .NET Framework 4.0 Client Profile or higher to run.">Installed OR NETFRAMEWORK40CLIENT</Condition>

<Property Id="WIXUI_INSTALLDIR" Value="INSTALLFOLDER" />
<UIRef Id="FooViewerInstallerUI" />
<UIRef Id="WixUI_ErrorProgressText" />
<Icon Id="FooViewerIcon" SourceFile="../FooViewer.ico" />
<Property Id="ARPPRODUCTICON" Value="FooViewerIcon" />

<!-- I got this upgrade code by opening one of the old .vdproj MSIs in Orca -->
<Upgrade Id="{80539F30-8176-4DCC-A102-ED32A34A91CB}">
  <UpgradeVersion OnlyDetect="no"
                  Minimum="0.0.0.0"
                  IncludeMinimum="yes"
                  MigrateFeatures="no"
                  IgnoreRemoveFailure="no"
                  Property="UPGRADE_VDPROJ_FOOVIEWER"
                  />
</Upgrade>
<Upgrade Id="{43e024b8-b3ea-40a3-a854-2af83f207f0f}">
  <!-- Foo Viewer 6.0.0.0 (Beta) shipped with a version 5.3.0.0 in the installer. -->
  <UpgradeVersion OnlyDetect="no"
                  Minimum="5.3.0.0"
                  Maximum="5.3.0.0"
                  IncludeMinimum="yes"
                  IncludeMaximum="yes"
                  MigrateFeatures="yes"
                  IgnoreRemoveFailure="no"
                  Property="UPGRADE_WIX_FOOVIEWER"
                  />

  <!-- Detect newer versions -->
  <UpgradeVersion OnlyDetect="yes"
                  Minimum="6.0.1.0"
                  IncludeMinimum="no"
                  Property="NEW_VERSION_FOUND"/>
</Upgrade>
<Condition Message="A newer version of Foo Corporation Foo Viewer is already installed.">
  Installed OR NOT NEW_VERSION_FOUND
</Condition>
<InstallExecuteSequence>
  <RemoveExistingProducts Before="InstallInitialize" />
</InstallExecuteSequence>
</Product>

However, despite putting in a <upgrade> element for the old installer's upgrade code, the old version isn't getting removed. As a result the new copy tries to install on top of the old copy, and then neither version works any longer.

The detection of the beta copy, and of newer versions, works correctly (the <Upgrade with GUID {43e024b8-b3ea-40a3-a854-2af83f207f0f} ). The beta version gets uninstalled, and if I generate a "newer" installer, then the current installer correctly doesn't install. That is, the WiX installers have no problem detecting each other.

Is there something I did wrong here that won't let it detect the old .vdproj installed copies?

EDIT: I tool a log of the installation process when this happens, I get the following:

Action start 17:25:47: FindRelatedProducts.
MSI (c) (10:B8) [17:25:47:269]: FindRelatedProducts: current install is per-machine.  Related install for product '{2024FF03-D6F2-4065-A22B-80252B2A66B6}' is per-user.  Skipping...
Action ended 17:25:47: FindRelatedProducts. Return value 1.

which appears to be accurate. The old installer gave an option for "Per User" or "Per Machine", whereas the new installer always forces per machine. If I select "Everyone who uses this computer" in the old installer, then the new installer is able to detect it. I would like to detect either option if possible in the WiX.

Upvotes: 2

Views: 2433

Answers (1)

Sasha
Sasha

Reputation: 8850

I'm afraid you can't deal with 2 different existing installations at the same time in single installer. Moreover you shouldn't try to run uninstallation of another product (since your UpgradeCode and ProductCode are different, it is anoter product) because msi can't work with simultaneous installations.

What I would recommend is creating separate exe application (bootstrapper), which will run child uninstallation processes of previously installed products and then immediately run your product's installation (probably in full UI mode).

To uninstall the product with no user interaction, use the following command:

msiexec /x {ProductCode} /qn

I hope you know the ProductIds of the previously installed products. If not, you can find it, searching the registry:

HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall\{ProductCode}\DisplayName

and HKEY_CURRENT_USER if application was installed for single user.

{ProductCode} mentioined in registry path is GUID which is your productCode. You should retrieve all nodes in "Uninstall" branch and find those which are your products checking the "DisplayName" attribute. I hope you know at least the name of the products installed =). And be careful not to delete all software on client's machine =)

Please note if you installed x86 application on x64 machine, you should search location

HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{ProductCode}\DisplayName"

One more important notice: if your bootstrapper will be also x86 application, you should retrieve node without "Wow6432Node" node because it will be automatically inserted in the requested path. Wonderful world of registry keys on different platforms =).

Please ensure your bootstrapper will be run with admin permission or will ask permission elevation (it should contain security manifest).

One assumption about problem in your post: maybe you didn't change the ProductCode when changed the UpgradeCode? I'm not sure how it will behave, but it is definitely not a MajorUpgrade which automatically removes the previously installed product. For more details see Wix documentation on upgrades. So you might got Minor upgrade or patch which directly installs new components on top of the previously installed files. That definitely could break the application.

Upvotes: 1

Related Questions