1

I have a WiX 3 setup project, using VS 2017 community with Wix toolset v3.11, install the output using:

msiexec /i cient.setup.msi /lv output.log

everything is good. uninstalling using

msiexec /x cient.setup.msi /lv output.log

is fine also. BUT if I rebuild the WiS setup project and then try and uninstall using the above command, I get the error 1602 from the MSI output. which is "This action is only valid for projects that are currently installed"

Here is the content of my Product.wxs file:

<?xml version="1.0" encoding="UTF-8"?>
<!-- The name of the product -->
<?define Name = "Notification Client" ?>
<!-- The manufacturer, for setup package publisher and folder info -->
<?define Manufacturer = "MyCompanies IT" ?>
<!-- The version number of this setup package-->
<?define Version = "1.0.1" ?>
<!-- UpgradeCode must be unique and not changed once the first version of the program is installed. -->
<?define UpgradeCode = "{GUID-HERE}" ?>

<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
  <?define ClientService_TargetDir=$(var.ClientService.TargetDir)?>
  <Product Id="*" Name="$(var.Name)" Manufacturer="$(var.Manufacturer)" Language="1033" Version="$(var.Version)" UpgradeCode="$(var.UpgradeCode)">
    <Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />

    <MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />

    <Feature Id="ProductFeature" Title="Client.Setup" Level="1">
      <ComponentGroupRef Id="ProductComponents" />
      <ComponentRef Id="ApplicationShortcut" />
    </Feature>
  </Product>

  <Fragment>
    <Directory Id="TARGETDIR" Name="SourceDir">
      <Directory Id="ProgramFilesFolder">
        <Directory Id="ROOTDIRECTORY" Name="$(var.Manufacturer)">
          <Directory Id="INSTALLFOLDER" Name="$(var.Name)" />
          <Component Feature="ProductFeature" Id="SetFolderPermissions" Guid="*">
            <CreateFolder>
              <util:PermissionEx User="Users" GenericAll="yes" />
            </CreateFolder>
          </Component>
        </Directory>
      </Directory>
      <Directory Id="StartupFolder" SourceName="Startup"/>
    </Directory>
  </Fragment>

  <Fragment>
    <DirectoryRef Id="StartupFolder">
            <Component Id="ApplicationShortcut" Guid="*">
              <Shortcut Id="StartupShortcut"
                   Directory="StartupFolder"
                   Name="Notification Client"
                   Target="[INSTALLFOLDER]\NotificationClient.exe"
                   WorkingDirectory="INSTALLFOLDER"
           />
              <RemoveFolder Id="CleanUpShortCut" Directory="StartupFolder" On="uninstall"/>
              <RegistryValue Root="HKCU" Key="Software\Microsoft\NotificationClient" Name="installed" Type="integer" Value="1" KeyPath="yes"/>
            </Component>
    </DirectoryRef>
  </Fragment>

  <Fragment>
    <ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
      <!-- TODO: Remove the comments around this Component element and the ComponentRef below in order to add resources to this installer. -->
      <!-- <Component Id="ProductComponent"> -->
      <!-- TODO: Insert files, registry keys, and other resources here. -->
      <!-- </Component> -->
      <Component Id="NotificationClient.exe" Guid="*">
        <File Id="NotificationClient.exe" Name="NotificationClient.exe" Source="$(var.ClientService_TargetDir)NotificationClient.exe" DiskId="1" KeyPath="yes" />
      </Component>
      <Component Id="NotificationClient.exe.config" Guid="*">
        <File Id="NotificationClient.exe.config" Name="NotificationClient.exe.config" Source="$(var.ClientService_TargetDir)NotificationClient.exe.config" KeyPath="no" />
      </Component>
      <Component Id="Newtonsoft.Json.dll" Guid="*">
        <File Id="Newtonsoft.Json.dll" Name="Newtonsoft.Json.dll" Source="$(var.ClientService_TargetDir)Newtonsoft.Json.dll" KeyPath="no" />
      </Component>
      <Component Id="Notifications.dll" Guid="*">
        <File Id="Notifications.dll" Name="Notifications.dll" Source="$(var.ClientService_TargetDir)Notifications.dll" KeyPath="no" />
      </Component>
      <Component Id="OHR_StdFunctions.dll" Guid="*">
        <File Id="OHR_StdFunctions.dll" Name="OHR_StdFunctions.dll" Source="$(var.ClientService_TargetDir)OHR_StdFunctions.dll" KeyPath="no" />
      </Component>
      <Component Id="OHR_MSGraph.dll" Guid="*">
        <File Id="OHR_MSGraph.dll" Name="OHR_MSGraph.dll" Source="$(var.ClientService_TargetDir)OHR_MSGraph.dll" KeyPath="no" />
      </Component>
      <Component Id="ServiceInstallation" Guid="*">
        <!-- Remove all files from the INSTALLFOLDER on uninstall -->
        <RemoveFile Id="ALLFILES" Name="*.*" On="both" />
      </Component>
    </ComponentGroup>
  </Fragment>
</Wix>

I have a feeling it is to do with a GUID issue, but I have followed the guidelines in other posts about uppercasing GUIDs and having the product Id re-generate every time to ensure upgrades can be rolled out without issues.

I'm new to Wix (this is my first project) therefore please be kind! :)

Stein Åsmul
  • 39,960
  • 25
  • 91
  • 164
Lee Hill
  • 13
  • 6
  • You can only uninstall an installed version. If you rebuild your project with Product Id="*" it is a different installation and thus not installed. – Palle Due Jan 15 '18 at 13:13

2 Answers2

1

You have set the Product GUID to auto-generate (which is fine). This means that every MSI you compile will have a new product GUID - naturally. You can invoke your MSI uninstall either via a specified MSI file or by specifying the product GUID to uninstall. See this little "reference" for information on this, your section would be section 3: Uninstalling an MSI file from the command line without using msiexec (this answer is a little long, please just focus on section 3).

You are specifying an MSI file to uninstall in your command which is not the MSI that is currently installed on the box - hence the product code embedded in the MSI is wrong for the current uninstall (what is installed is one of your previous builds - with a different product GUID).

You can locate the original MSI that was used to install on the box (if you still have it), and then your command msiexec /x cient.setup.msi /lv output.log will work, or you can figure out what the product code for the installed product really is, and then you uninstall like this: msiexec /x {PRODUCT-GUID} /lv output.log. This will always work once you find the correct product GUID. This uninstall runs from a cached copy of your original MSI in %SystemRoot%\Installer (super-hidden folder).

Here is one way to find the product GUIDs for installed products: How can I find the product GUID of an installed MSI setup? (this answer is also a little long, just look for the PowerShell command - it will do).


UPGRADE: If you don't create a new product GUID for each setup, then you can not use a major upgrade. What you get then is a minor upgrade. This has to be installed in a different way than a major upgrade. Most people use major upgrades since they are more flexible. You need to implement a major upgrade to make your newest setup silently uninstall the existing setup as it is installed, otherwise you get two entries in add / remove programs as you state.

Setting up a major upgrade: How To: Implement a Major Upgrade In Your Installer.

And I will add the link you suggest yourself: How to implement WiX installer upgrade?.

Stein Åsmul
  • 39,960
  • 25
  • 91
  • 164
  • thanks for the quick response, I thought that this was the case, so I have changed the ProductID to be fixed, and now I get a different error when going through the same process... "Another version of this product is already installed..." which doesn't make sense as I now have a fixed Product ID, my version and UpgradeCode are still the same. this wouldn't be a problem, but if keep the ProductID as auto, and I push out an update, it just adds another entry into the programs and features, instead of updating the existing entry. I understand why as the Product ID is different. – Lee Hill Jan 15 '18 at 15:45
  • having had a look around i can, i have found this post [here](https://stackoverflow.com/questions/114165/how-to-implement-wix-installer-upgrade/724098#724098) detailing how to uninstall old versions before an update, and inevitably a rebuild of the msi package. which solves my problem. so i will mark your response as the answer. – Lee Hill Jan 15 '18 at 15:59
  • p.s. if you think my question would be useful to other new Wix users, please upvote my question :) – Lee Hill Jan 15 '18 at 16:02
  • Yes, your question was pretty well formatted, but I have fixed it up a bit to eliminate GUIDs (they could otherwise be copied and you could get problems - GUIDs should never be re-used by others). Always remember to remove any such "[sensitive data](https://stackoverflow.com/a/48051210/129130)" from your sources posted online. Also, please consider up-voting all helpful answers as well. – Stein Åsmul Jan 15 '18 at 16:28
0

The upgrade code is used to enumerate potential candidates to remove in lieu of a pending installation. When you rebuild, the /Wix/Product[@Id] is regenerated and hence this appears as a new product which simply can "upgrade" anything with the existing upgrade code that you maintain.

Ritmo2k
  • 993
  • 6
  • 17