Static analysis of MSIs as part of a CI build

Thursday, October 25, 2007 – 2:35 PM

A couple of weeks back Alan Ridlehoover and I gave a talk about continuous integration (CI) for the engineering excellence group here at Microsoft. We had a pretty good turnout and a lot of good questions at the end.

One of the things that occured to me during the talk was that I could do some testing on our MSIs as part of our CI build. Why not do static analysis on MSIs? We’ve been having some issues with our installer while finishing off Service Factory: Modeling Edition. Installer issues took a long time to find and required

What I really needed to do is run the MSI validator msival2.exe (which ships with the Windows Installer SDK) during my build and parse the output.

The validator output is just text and looks something like:

ICE{nn} {WARNING|INFO|ERROR|...} {Description}

So the trick is parsing this mapping each line into an MSBuild error or warning. For now let’s ignore the INFO lines, you can tell msival2.exe to skip these with the -i flag. I’d like to end up with an XML file like this:

MsiValidationEntry code="nn" type="WARNING">

I wrote a build task to reformat the output and then use an SDC task to generate warnings and errors from the XML.

The MSBuild task is very straightforward you can download the source and (NUnit) unit tests for it here. Hooking it up to the build script is easy too; exec the msival2 command to generate a log file, convert it to XML and then parse the XML to

<Target Name="ValidateMSI"
  <CreateProperty Value="$(InstallerWorkDir)validation.log">
Output PropertyName="ValidationLog" TaskParameter="Value" />
<CreateProperty Value="$(InstallerWorkDir)validation.xml">
Output PropertyName="ValidationXml" TaskParameter="Value" />
  <Delete Files="$(ValidationLog)"
Condition="Exists('$(ValidationLog)')" />
<Exec Command="$(ToolsBinDir)msival2.exe "$(InstallerWorkDir)$(OutputMSIFile)" "$(ToolsBinDir)darice.cub" -f -l "$(ValidationLog)" "
IgnoreExitCode="true" />
MsiValToXmlTask Path="$(ValidationLog)" Output="$(ValidationXml)" />
XPath="//ArrayOfMsiValidationEntry/MsiValidationEntry[@type='ERROR']" >
<Output ItemName="MsiErrors" TaskParameter="Results" />
  <Warning Text="ERROR: %(MsiErrors.Identity)" Condition=" '@(MsiErrors)' != '' " />
Error Text="Validation failed." Condition=" '@(MsiErrors)' != '' " />

Obviously your ValidateMSI task needs to take a dependency on your build MSI task so it executes in the correct order. You also need to set ToolsBinDir, InstallerWorkDir and OutputMSIFile correctly for the task to execute. For clarity I’ve only shown error generation but you could add other messages for each type of MsiVal event.

And there you have it. Robert’s your father’s brother (as they say at home). Static analysis of MSIs are part of your build process with error output into MSBuild and thus your CI server.

Other points to note: Wix 3.0 runs validation as part of candle/light so this tool isn’t really needed if you’re on 3.0 (we’re not there yet). The msival2.exe takes some sort of dependency on something else in the installer SDK (I’ve not had time to figure out what). So don’t just copy the executable to your build server, it’ll give you a COM error.

  1. 3 Responses to “Static analysis of MSIs as part of a CI build”

  2. Exactly what I was looking for! You save me several hours of work where I needed to filter msival2 log output and your article posted here is very much appreciated!


    By Richard Cunday on Feb 4, 2009

  3. I liked this blog very much it gives me inspiration to do something more. This is a blog which is full of great knowledge and it is really a good work to share our knowledge with others. Great Job…

    By website for mobile on Jun 2, 2010

  1. 1 Trackback(s)

  2. Oct 26, 2007: #2872 » Blog Archive » Gotchas: MSTest test projects don’t load on VS Pro

Sorry, comments for this entry are closed at this time.