Friday, March 6, 2009

Debugging InstallUtil.exe

The project I'm currently working on contains a Windows service with a number of performance counters. To run the code on a dev machine, we prefer to do so without first running an msi. So to get the performance counters installed, we tried to run installutil on the service executable. Which of course returned a vague error message and rolled back the changes. Fortunately, this type of problem wasn't too difficult to debug.

To demonstrate, I've created a new application and added a class that inherits from Installer. I've overridden the OnBeforeInstall event as follows:

protected override void OnBeforeInstall(IDictionary savedState)
{
    base.OnBeforeInstall(savedState);
 
    string nullString = null;
    int invalidLength = nullString.Length;
}

If I attempt to run "InstallUtil MyApp.exe" I receive the following within the console output:

An exception occurred in the OnBeforeInstall event handler of MyApp.MyAppInstaller.
System.NullReferenceException: Object reference not set to an instance of an object.


For trivial code such as my above sample, tracking down the problem should take most developers all of five minutes. Once you have a non-trivial amount of code (which was the case at work) you need a little more information. If I call "InstallUtil /ShowCallStack MyApp.exe" I receive the exact line where the problem occurs:

An exception occurred during the Install phase.
System.InvalidOperationException: An exception occurred in the OnBeforeInstall e
vent handler of MyApp.MyAppInstaller.
at System.Configuration.Install.Installer.Install(IDictionary stateSaver)
at System.Configuration.Install.Installer.Install(IDictionary stateSaver)
at System.Configuration.Install.AssemblyInstaller.Install(IDictionary savedState)
at System.Configuration.Install.Installer.Install(IDictionary stateSaver)
at System.Configuration.Install.TransactedInstaller.Install(IDictionary savedState)
The inner exception System.NullReferenceException was thrown with the following
error message: Object reference not set to an instance of an object..
at InstalUtilDebugging.MyAppInstaller.OnBeforeInstall(IDictionary savedState)
in C:\source\temp\InstalUtilDebugging\MyAppInstaller.cs:line 23
at System.Configuration.Install.Installer.Install(IDictionary stateSaver)


In many cases, this will be enough to solve the problem. There may be cases, however, where you need to attach a debugger to the process and step through the code to see where a problem actually started. To do this I add the following line to the beginning of OnBeforeInstall:

System.Diagnostics.Debugger.Launch();

After I recompile and again run InstallUtil, I am given a JIT Debugger dialog which allow me to attach to the process.


I select the instance of VisualStudio that has my install code and click 'Yes' to begin debugging. You may be given a warning stating "There is no source code available for the current location." Click 'OK' and press F10 once - this will show the Debugger.Launch statement as the current line of code being executed. From here debugging works as in any application.

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.