Tuesday, October 19, 2010

Modifying a Visual Studio web setup program to include a physical directory

When I was working on creating a new web application for a customer, I ran into a problem with the setup program. The default Web Setup project for VS2008 does not allow you to specify the physical install location for your application, but instead installs it in c:\inetpub\wwwroot. This wasn't going to work for my customer, who needed to be able to specify the physical directory. I could have used a regular setup project, which allows the end user to specify the physical install directory, but then the setup program wouldn't take care of creating the virtual directory in IIS. After some hunting, I found a solution that allows you to modify the setup MSI file so that the user can specify the physical install directory.

The process of modifying the MSI file is rather tricky, since it essentially involves modifying the MSI file once while Orca records your actions. I screwed it up the first time and had to start again. The shortcut is that you're welcome to use the MST file I created with this process to save yourself the trouble of creating the MST.

Now for the steps:

Obtain Orca.exe
Orca is part of the Windows SDK which can be downloaded at this link. After downloading and installing the SDK, browse to "Program Files\Microsoft SDKs\Windows\v7.0\Bin" and run Orca.msi to install the Orca utility.

Create the MST to be used to modify the MSI
These instructions are from this codeproject link. This assumes you've already created the MSI for the Web Setup project.
We'll use Orca to essentially record the changes you make to an MSI file; these changes will be saved in an MST file which you can then apply to other MSI files to perform the same changes.
  1. Run orca.exe
  2. Use File - Open to open the MSI
  3. Under Tools - Options - Database check Copy embedded streams during 'Save As'
  4. Under the Transform menu select New Transform to start recording a transform.
  5. In the screen shot image on the right (click to view it full-size) are shown 5 tables. Add the rows outlined in green to each table (Control, ControlEvent, CustomAction, InstallExecuteSequence, InstallUISequence).
  6. In the Control table, the Control_Next must refer to another control on that dialog, and all the controls must refer to each other in a loop. Since we added some extra controls to the WebFolderForm dialog, we need to modify one of the existing controls to refer to one of our new controls. Modify the AppPoolsCombo control (on the WebFolderForm dialog) and set the Control_Next column to be InstallLabel.
  7. We also have to remove some rows that would otherwise set the TARGETDIR back to the default:
    • In ControlEvent delete the row that has Dialog=WebFolderForm and Control="Next" and Event="DoAction"
    • In InstallExecuteSequence delete the WEBCA_EvaluateURLs action.
    • In InstallUISequence delete the WEBCA_EvaluateURLsNoFail action.
    • You're now done recording the Transform. From the menu choose Transform - Close Transform and save the transform (it will have a .MST extension).
A shortcut
This MST file was generated using the steps above for a VS2008 web setup project and should be able to be used as is to apply this transform to web setup MSI files.

Applying the transform
Now that you have an MST (transform) file, you need to use it to modify the setup MSI file.

You can apply a transform using Orca; open the MSI you want to transform, then from the menu choose Transform - Apply Transform, select the .MST file to use and it will modify the MSI. You can then save the MSI file.

You can also apply the transform via the command line using MsiTran.exe, which is installed with the Windows SDK (in Program Files\Microsoft SDKs\Windows\v7.0\Bin).

Applying the transform as part of a TFS (Team Foundation Server) build
In my case, I wanted to have this automatically done as part of the TFS (Team Foundation Server) build process we use. That's actually fairly simple. To apply the transform as part of a TFS build, copy the msitran.exe and your MST transform file to the build server. You can then modify the TFSBuild.proj file by adding an Exec such as the following to the AfterCompile target:

<Exec Command="c:\bin\msitran.exe -a c:\bin\WebSetupWithPhysicalDir.mst "$(OutDir)Setup\WrtServicesSetup.msi""/>

Results
When the setup program is installed on a Windows server, which can have multiple websites and application pools, the install screen should look something like this: