RobMensching.com /Blog
when setup isn't just xcopy

Posted by
Rob Mensching
Thursday, September 13, 2007 10:16 PM

Make the impossible possible then talk about it.

Derek made a guest appearance tonight at the weekly WiX toolset coding night. It was fun having him around again.  We all caught up on the things that have happened in the last year or so. At the end of the night (about 1 AM), I dropped him off at his hotel downtown and drove back home. On my way home, I remembered a recent comment that was directed at Derek and I:

Derek and Rob, wouldn't it be better to first document all the current 3.0 features (SecureObj, Torch, Pyro, Setupbld etc) then [sic] adding support for a beta?

My simple answer is, "No." I think it is better to ensure that the WiX toolset supports as many of the available scenarios correctly as quickly possible. My primary goal is to make sure that setup developers can get their job done well and that the tools are not the obstacle blocking them.

That said, I recognize that documentation can greatly improve the speed at which developers can learn the tools. You will notice that with many of the new features going into the core toolset that there is a great deal more documentation than what has been provided in the past. We obviously have a lot of "documentation debt" that still needs filling in.

Ultimately though every user of the WiX toolset has access to the deepest level of documentation, the source code. As long as the WiX toolset supports the full set of features available from the Windows Installer then any developer can learn how to use them.

 

PS: No, I am not trying to argue that documentation is irrelevant. I'm just saying that with the finite number of resources that I have to put toward the project, making the impossible possible currently seems more valuable than going back and writing more documentation for that which is already possible.

 


Posted by
Rob Mensching
Thursday, September 13, 2007 9:47 PM

Zataoca: Custom actions should be data driven.

As I noted a few months ago, the Windows Installer is a declarative installation engine not a procedural installation engine. That means if you are going to extend the installation engine (which is what custom actions essentially do) then you should follow the same principles the engine follows. Namely, your custom action should read data out of a table and act based on those declarative instructions.

Let me give an example. Let's say you want to protect some user input (maybe a password) using DPAPI.* Your first thought should be, "What are the inputs to my custom action?" Those inputs are the columns for your custom action's table. In this case, one column would contain the value to be encrypted (Formatted so the value of a Property could be encrypted).  Another column would provide the optional entropy value (that helps further randomize the protected output). A third column would specify whether the value will be protected for the current user or as the local machine account (limiting the set of users that can decrypt the data). A final column would specify the name of the Property to output the encrypted value to.

Then you would write your custom action to read each row out of the table with those for columns and call the ::CryptProtectData() API filling in the appropriate parameters. By acting on the data from the custom table, we call your custom action a "data driven custom action".

Those of you whose first instinct was to say, "Oh, I'll just write the code to get the value of a property called FOO and call the ::CryptProtectData() function with a bunch of parameters and write the value back out to a property called BAR." should go back an reevaluate all of the custom actions you've ever written. This type of custom action is what we call a "procedural custom action" and it is inferior to the data driven method. Unfortunately, to most developers procedural custom actions are also the most intuitive way to write code (because that's how most code is written).

Data driven custom actions are better than procedural custom actions for many reasons. as noted in the beginning, data driven custom actions follow the same declarative model that the rest of the Windows Installer follows. That means you fit into the rest of the installation system appropriately

One example is that data driven custom actions can be affected by transforms. You might think, "Oh, well I don't support administrative customizations so I don't care about transforms." That might be true but the most optimal form of patching uses transforms to affect the package. If your custom actions are not data driven, your transform must patch the custom action binary directly and that creates a much larger patch.

Data driven custom actions are also reusable. Another developer can use your custom action without modifying the code because the inputs all from from a table. The custom action library that comes with the WiX toolset works just like this. We write the actions to configure things like Users, FileShares, Web Sites, Virtual Directories, SQL Databases, etc and you can reuse those actions by providing your own data. Data driven custom actions paired with the extension model in WiX provides a very powerful platform for installation.

Data driven custom actions are also more transparent than procedural custom actions. Going back to the WiX toolset Web Site example. If you look at the tables in the MSI after adding a WebSite element it is very possible to predict what the installation is going to do. Procedural custom actions hide the data and the actions in the compiled code (you don't write script custom actions do you?). Admittedly, the data driven custom actions still have code in a black box but well written data driven custom actions can be quite transparent. Take a spin through the WiX custom action library if you don't believe me.

Now I wanted to say that *all* custom actions should be data driven from a table but there are some rare cases where it doesn't make sense. The custom action at the end of the install that launches your "readme.txt" through a ::ShellExecute() may just need a simple property passed to it (that's how the WixShellExec custom action works today).

However, any custom action that modifies system state (see #3 in my list of custom action classes) should definitely be a data driven custom action to participate in the installation transaction well. After I do an example of a data driven internal-only custom action (#1 from the list), I'll dive into system modification custom actions and further demonstrate why they should be data driven.

Anyway, that's a long blog entry that basically says, "If you have already failed and determined that you need a custom action, make sure you make it data driven."

 

* Yes, I am going to walk step by step through this example at some time in the future.

 


Posted by
Rob Mensching
Monday, September 03, 2007 6:46 PM

Windows Installer 4.5 and the WiX toolset.

If you follow the world of the Windows Installer at all, I'm sure you have noticed that the Windows Installer 4.5 Beta was made available last week.  Navigating the Connect sign up process is incredibly onerous but necessary if you want to get a hold of the new MSI.CHM and see the feedback provided thus far.

If you follow the WiX toolset then you might be wondering what our plans are for supporting MSI 4.5.  Well, last Thursday I read through the new features.  There were three new bit flags and two new tables that would need coverage in the WiX toolset.  Since adding new bit flags is usually quite easy, I whipped out the changes for the three new bit flags in both WiX v2 and WiX v3 that night.

Of course, nothing is that simple and I ran into two problems:

  1. The new msidbCustomActionTypePatchUninstall value is 0x8000 (32768). Unfortunately, that value goes into the CustomAction.Type column that is defined as an Integer (i2).  The Integer column in MSI only supports values from -32767 to 32767.  So I would need to bump up the Type column to a DoubleInteger (i4). Unfortunately, if I did that then the new versions of the WiX toolset would not be able to patch previously created MSI files (because you can't transform column types in MSI). Does anybody else find it ironic that a bit flag added to enable more patching scenarios actually makes it impossible to patch older MSI files?
  2. The Windows Installer 4.5 Beta did not ship a new .cub file that understands the new bit flags. Thus, when you build an MSI using WiX v3 (that automatically validates your MSI files after link) that has one of these new bit flags you will always have an ICE45 error. Fortunately, we can suppress ICE45 in WiX v3 by added "-sice:ICE45" to the light.exe command-line.

 After thinking about these problems for a couple days, I decided to back out my changes to WiX v2.  I decided to back out the changes because WiX v2 is supposed to be our stable branch and adding support for a Beta release of the Windows Installer seems to go against that goal. I'll add full support to WiX v2 when MSI 4.5 releases.

I also chose not completely support msidbCustomActionTypePatchUninstall in WiX v3 yet. WiX v3 has the new attribute (CustomAction/@PatchUninstall='yes/no') for the new bit flag but if you use it your MSI will fail to link because the CustomAction.Type column definition is still Integer (i2) and 0x8000 won't fit. This is a big problem for authoring tools and developers so I expect the Windows Installer team is going to have to come up with a different solution (like add a new column on the end of the CustomAction table called TypeEx  <grin/>).

That just left the new MsiEmbeddedUI and MsiEmbeddedChainer tables for the core WiX toolset to support all of the MSI 4.5 Beta features. So I sat down today, busted out the changes to WiX v3 to support the new tables, got Bob to review the changes and checked all of the changes in.  You can see support for the MSI 4.5 Beta in CVS right now.  We'll have a build tomorrow so people can start playing with the new features, if they so choose.

So that's the plan.  When MSI 4.5 releases (early next year, I hear) WiX v2 will be enhanced to support the new features.  WiX v3, on the other hand, has support for the new MSI 4.5 features about 10 days after the Beta was released.  We'll keep updating WiX v3 as more details are made available by the Windows Installer team.