Mailbag: How can I customize an MSI in the Visual Studio setup/deployment project?

Question:

I am using the Visual Studio setup/deployment project to create an MSI to install my application. I would like to add some functionality to this MSI that does not appear to be supported in the Visual Studio IDE (such as modifying the default install path based on a registry value on the system). I know how to do this by directly editing the MSI, but I don't want to have to manually edit the MSI each time I build. Are there any other options I can use in this scenario?

Answer:

There is a limited set of customizations you can make to an MSI in the Visual Studio IDE UI for a setup/deployment project. By limited, I mean that there are a lot of features that are natively supported in Windows Installer MSI format that are not exposed for customization in the Visual Studio IDE. Examples include changing the default install path based on a registry value, advanced setup UI features such as updated banner text or a "launch my product" checkbox on the final screen, creating custom actions that reference external executable files, or setting various custom action attributes (among other things).

If you would like to automate the ability to customize an MSI that is built by the Visual Studio setup/deployment project in a way that is not currently supported by the UI in the Visual Studio IDE, you can write a script that accesses the Windows Installer object model to perform these customizations. Then you can create a post-build step in your Visual Studio setup/deployment project to run your script after the MSI has been built so that the final result each time you build will be an MSI package with your additional customizations made to it.

As an example, you can use the sample script at this location to add a checkbox to your MSI's setup UI that will let the user choose whether or not to launch your product after setup finishes.

If you would like to include this script as a post-build step in a Visual Studio setup/deployment project, you can use the following steps:

  1. Download the sample script and extract the contents to the directory that contains the Visual Studio setup project you are working on.

    Note: You should end up with the file EnableLaunchApplication.js in the same directory as the .vdproj file for your setup project. The rest of these steps will not work correctly if you do not put EnableLaunchApplication.js in the correct location, so be careful about this step.

  2. Open the file EnableLaunchApplication.js in a text editor such as notepad, locate the variable at the top of the file that is set to the value WindowsApplication1.exe, and change it to the name of the EXE that is in your setup that you want to launch when the MSI is done installing

  3. Open the project in Visual Studio

  4. Press F4 to display the Properties window

  5. Click on the name of your setup/deployment project in the Solution Explorer

  6. Click on the PostBuildEvent item in the Properties window to cause a button labeled "..." to appear

  7. Click on the "..." button to display the Post-build Event Command Line dialog

  8. Copy and paste the following command line into the Post-build event command line text box:

    cscript.exe "$(ProjectDir)EnableLaunchApplication.js" "$(BuiltOuputPath)"

  9. Save your project

  10. Build your project in Visual Studio

Note that the quotation marks in the command line in step 8 are very important because the script will not work correctly without them. Make sure to double-check that you have put quotes in the proper places.

<update date="8/23/2006"> Updated the steps needed to configure post-build commands in the Visual Studio UI because they are different for setup projects than for other Visual Studio project types </update>

<update date="5/31/2007"> Updated steps to mention the need to rename WindowsApplication1.exe to the name of the EXE in each project that you want to launch. Also fixed a typo in the variable BuiltOuputPath. </update>

<update date="8/26/2008"> Updated steps to be more specific about what folder to save EnableLaunchApplication.js to </update>

<update date="3/15/2009"> Fixed broken link to the sample script </update>

<update date="7/26/2012"> Fixed bad HTML formatting and misnumbered steps </update>

<update date="2/8/2016"> Fixed broken link to Windows Installer object model documentation </update>