Translate

Friday, February 20, 2009

Extending Installer Custom Actions with Visual Studio Installer

The Visual Studio Installer custom actions are fairly useless if you want to control when your custom action is executed (outside of the options provided by Visual Studio). So instead of using a Visual Studio Installer custom action, I used a post build step for the installer and used my own program to modify the MSI post build.

What I really want to do:
  • Execute a custom action before the Installer UI is displayed to the user
  • Execute a custom action after the user chooses to install the product, but before files are copied to the computer.
  • Execute a custom action after all files have been copied to the computer.

Tools Needed:
  • Orca (Views and edits MSI databases visually)
  • MSI.Interop (If you want to write the Installer post build step in managed code)
Using the Orca program, open your MSI file (already built). The two tables we will be working with are InstallUISequence and InstallExecuteSequence. The InstallUISequence and InstallExecuteSequence tables are actions executed by the intaller in the order defined by the Column 'Sequence'. Your custom action will need to be placed somewhere in this sequence with a unique sequence number. For my custom actions I will use the following numbers:
  • InstallUISequence - Sequence 920 (Happens before a UI is displayed).
  • InstallExecuteSequence - Sequence 1050 (Happens after the user chooses to install the product but before files are copied to the system).
  • InstallExecuteSequence - Sequence 6700 (Happens after all files are installed but before the user exits the installer).
So, how do we translate this into code? I already have my custom action DLL built and three functions exported (PreProcess, Process, and PostProcess) in the file CustomAction.dll. The post build program for the installer must insert the DLL into the MSI, and insert the three sequences in the two Install tables.

Example code for the post-build executable is below:


// Open the MSI
Pahvant.MSI.Database db = new Database("myInstaller.msi", Pahvant.MSI.Database.OpenMode.Transact);

// Insert the custom action DLL into the MSI
Pahvant.MSI.Record rec = new Pahvant.MSI.Record(1);
rec.SetStream(1, @"c:\path_to\CustomAction.dll");
Pahvant.MSI.View binView = new Pahvant.MSI.View("INSERT INTO `Binary` (`Name`, `Data`) VALUES ('CustomAction', ?)");
binView.Execute(rec);

// Insert the custom action functions (the ones exported from the DLL) into the MSI
Pahvant.MSI.View caView = new Pahvant.MSI.View("INSERT INTO `CustomAction` (`Action`, `Type`, `Source`, `Target`) VALUES ('PreProcess', 1, 'CustomAction', 'PreProcess')");
caView.Execute();
caView = new Pahvant.MSI.View("INSERT INTO `CustomAction` (`Action`, `Type`, `Source`, `Target`) VALUES ('Process', 1, 'CustomAction', 'Process')");
caView.Execute();
caView = new Pahvant.MSI.View("INSERT INTO `CustomAction` (`Action`, `Type`, `Source`, `Target`) VALUES ('PostProcess', 1, 'CustomAction', 'PostProcess')");
caView.Execute();

// Insert the rows to call the custom action at the proper time in the installer sequence
Pahvant.MSI.View seqView = new Pahvant.MSI.View("INSERT INTO `InstallUISequence` (`Action`, `Condition`, `Sequence`) VALUES ('PreProcess', '', 920)");
seqView.Execute();
seqView = new Pahvant.MSI.View("INSERT INTO `InstallExecuteSequence` (`Action`, `Condition`, `Sequence`) VALUES ('Process', '', 1050)");
seqView.Execute();
seqView = new Pahvant.MSI.View("INSERT INTO `InstallExecuteSequence` (`Action`, `Condition`, `Sequence`) VALUES ('PostProcess', '', 6700)");
seqView.Execute();

// Commits the changes to the MSI.
db.Commit();


Now you can set the program you created to run as a post build step for your Visual Studio Installer. I know I haven't explained how to write a custom action DLL, but there's many references online and I might provide an example in the future.

What would you want to do during each custom action?
  • In the PreProcess step you may want to store some information such as previous version information, or install pre-requisites outside of the Visual Studio pre-requisites.
  • In the Process step you may want to backup configuration files that may be overwritten during an upgrade
  • In the PostProcess step you may want to display application configuration dialogs to the user or copy extra files from your installer location.

No comments:

Post a Comment

Codementor

Ryan Kuhn

★★★★★

Expertise