Setup

Zataoca: Classes of Custom Actions

Continuing the Zen and the Art of Custom Actions thread, I thought I'd post a mostly formed thought. When I'm presented with the need to write a custom action I often mentally classify the work into one of three or so different buckets.

Now, I’m not sure the ideas presented here in capture exactly everything the way I want but it seems like a decent place to start discussion. So, on with the classifications.

  1. Internal-only custom actions. This class of custom actions operates purely on data available inside the MSI database. Assigning a Property the value of another Property is a simple internal-only custom action. A custom action that reads some table in the MSI and populates some other table with temporary rows is also an internal-only custom action. Internal-only custom actions are usually easier to design and implement because their data is contained completely within the MSI itself. Since internal-only custom actions do not interact with the “outside world” (i.e. anything on the machine) they usually have very few dependencies.

  2. Read-only custom actions. This class of custom actions reaches out on to the machine to gather data for some other process of the install. Usually, read-only custom actions access some data store (registry, SQL database, file system) and populate a Property or some table inside the MSI for later processes to act on. These custom actions are usually a bit more complex than the internal-only custom actions because you have to think about what user context you are accessing the machine with (Local System or the installing user that is elevated or not). Read-only custom actions also have to be robust to handle whatever circumstances they might find on a user’s machine. Basically, there are a lot more unknowns when you start to reach outside of the MSI database and the code often has more dependencies that can fail.

  3. System modification custom actions. This class of custom actions is by far the most complex custom action to write. These are the custom actions that go out and change some state on the machine. They do all kinds of things from creating registry keys (bad, use the Registry table) to writing ACLs (yeah, I know the LockPermissions table sucks) to updating the IIS metabase (that’s what the standard WiX IIS CustomActions do) to talking to SQL Server (WiX SQL CustomActions can do much of that) to changing any other number of bits on the user’s machine. System modification custom actions are difficult because they not only have to consider the context they are operating in, they usually have to be deferred (which is a fascinating set of future topics). On top of that, system modification custom actions need to think about what they do to the machine when installing, uninstalling, repairing, patching and rolling back all of those operations. Needless to say, designing, developing and testing system modification custom actions is a very onerous process. I dread having to write a custom action that modifies the system state.

Anyway, that’s the three major classifications of custom actions that I typically consider. There are probably different ways to split the classifications. For example, launching a program at the end of the install is something that I would consider a read-only custom action or a system modification custom action depending on whether the launched application modifies system state. In any case, these buckets tend to capture most of the concerns I immediately think about when the need for a custom action arises.

We’ll talk about custom actions more later. Eventually, I’ll even get around to writing code or dissecting existing custom action code.