WiXSetup

How to create an uninstall shortcut (and pass all the ICE validation).

A while ago, I saw this blog post about creating an uninstall shortcut using the WiX toolset. My first reaction was, "Uhh, I thought the Logo says you're not supposed to create uninstall shortcuts." But as the blog author noted clients are clients (especially if they are paying the bills). My second reaction to the blog entry was, "Jeez, those CustomActions don't seem like they should be necessary."

Well, it turned out that I’ve been doing a lot of demos recently. When creating the demo code, I found that having an uninstall shortcut installed turned out to be really handy. I routinely forget to uninstall the application package during my demos (which often messes up later demos) and the shortcut serves as a very handy reminder to clean up after myself. Saves me from click over to Add/Remove Programs (ARP) as well.

Anyway, since I blogged a bunch of random personal goo tonight, I thought I’d wrap up by sharing my solution for creating an uninstall shortcut without using any CustomActions.

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
  <Product Id="PUT-GUID-HERE" UpgradeCode="PUT-GUID-HERE"
           Name="TestUinstallShortcut" Language="1033"
           Version="1.0.0" Manufacturer="Microsoft Corporation">
    <Package InstallerVersion="200" Compressed="yes" /> 

    <Media Id="1" /> 

    <Directory Id="TARGETDIR" Name="SourceDir">
      <Directory Id="ProgramMenuFolder">
        <Directory Id="ShortcutFolder" Name="My Application">
          <Component Id="UninstallShortcutComponent"
                     Guid="PUT-GUID-HERE">
            <RegistryKey Root="HKCU"
                         Key="Software\My Application\Uninstall">
              <RegistryValue Value="RobMen Was Here." Type="string"
                             KeyPath="yes" />
            </RegistryKey> 

            <Shortcut Id="UninstallProduct" 
                      Name="Uninstall My Application"
                      Target="[System64Folder]msiexec.exe"
                      Arguments="/x [ProductCode]"
                      Directory="ShortcutFolder"
                      Description="Uninstalls My Application" />
            <RemoveFolderId="RemoveShorcutFolder" On="uninstall" />
          </Component>
        </Directory>
      </Directory>
    </Directory> 

    <Feature Id="TestUninstallShortcut" Level="1"
             Title="Test Uninstall Shortcut Feature">
      <ComponentRef Id="UninstallShortcutComponent" />
    </Feature>
  </Product>
</Wix>

The only interesting part in this example is inside the Component element. In there are actually a few interesting things to notice:

  1. As noted on the other blog entry, the registry key is created to make ICE18, ICE38 and ICE48 happy. I know the registry key is recommended to make things work correctly for roaming user profiles (how many people use that? I don’t know) but I don’t understand why the ICEs aren’t comfortable with me using the ShortcutFolder as the keypath (it is in the user’s profile and should be just as good as the registry key as the key path). I believe it has something to some minutia in the way that Group Policy and the Windows Installer interact.

  2. The Shortcut/@Target uses the System64Folder standard directory as the root for msiexec.exe. I use System64Folder because that always resolves to the native “system32” directory on the operating system (SystemFolder resolves to the “SysWow64” directory on 64-bit operating systems). Now, I’m not a 64-bit guru and I don’t have access to a 64-bit OS right now so I could be wrong about System64Folder but my instincts say this is the right thing. It works on 32-bit XP, I tested. <smile?>

    Note: I use the “[PropertyFolder]executable.exe” syntax here because I did not install the msiexec.exe (obviously, since that’s the Windows Installer itself). If the shortcut pointed at a file I installed then I would have used the ”[#FileId]” syntax instead.

  3. The Shortcut/@Arguments passes the “uninstall command” (/x) plus the standard property for the product code of the package. This is much simpler solution that proposed in the other blog entry.

  4. The Remove folder element exists to make ICE64 happy. Like the registry key listed above, this cleans up things in a roaming user scenario. I wish these quirky behaviors weren’t exposed to package developers and that the Windows Installer would just “do the right thing”. There must be some crazy scenarios where the Windows Installer can’t figure out things for itself.

Anyway, that’s about the simplest .wxs file that I can think of to create an MSI that installs an shortcut to uninstall itself.

Silly? Yes.

Helpful? Hopefully. You should be able to use this information as a starting place to install shortcuts that point at more useful things (like your own application).

More complicated than it should be? Definitely. The ICEs add a registry key and remove folder entry that I don’t want/need. I’m considering adding some syntactic sugar to the WiX schema to simplify the authoring in this case but I’m concerned about creating a registry key unexpectedly. Or maybe we can just convince the Windows Installer team to change the requirements that make these ICEs necessary.

In the mean time, keep coding, you know I am.