Wednesday, January 16, 2013

Everyone vs. Just Me for Custom Actions Installer Classes

This post explains how to change the behavior of your Custom Actions Installer class depending on the user choice in the dialog box:

The Problem

When you create a Custom Action project to be called from a Visual Studio 2010 Setup project, you subclass System.Configuration.Install.Installer. This will then be called from the Visual Studio 2010 Setup project, passing in some context information about the installation via the Context.Parameters StringDictionary.

Except it doesn't contain the information about wether the user chose "Just Me" or "Everyone"!

The Solution

I came across this page that explained how to pass in information to Context.Parameters in the custom action: You can use the CustomActionData property to add values to Context.Parameters.

The trick is, to use the format "/varname=value", and variable substitution happens for Windows Installer Properties, if they are enclosed in square brackets...

After googling a bit more, I found a msdn page containing the Windows Installer Property Reference and searching that, I found the property ALLUSERS. This is set to the string "1" if the user chose to install for "Everyone" and set to the empty string "" if the user chose to install for "Just Me".

Putting two and two together, I added the string "/allusers=[ALLUSERS]" to the CustomActionData property for the custom actions. And then can query this inside the Installer class:

if (Context.Parameters["allusers"] == "1")
    // user selected "Everyone"
    // user selected "Just Me"

Testing this proved that the ALLUSERS property is retained by the Windows Installer and can also be used for uninstalling.

Context: Installing Revit Addins

When installing addins for the Autodesk Revit product, a manifest file has to be created and placed in a specific directory. There are two addin directories to choose from: One for the current user and one for all users of the system.

The RevitPythonShell installer for Revit 2013 has been updated with the above technique to install to different locations based on the users choice. You can see a working example of what the custom action code looks like in the RevitPythonShell source for the RegisterAddinCustomAction class.