26. October 2008
This is my fifth post in my WiX and DTF series. Here are some others I’ve written:
After working quite a bit with Custom Actions (CA’s) in managed code I thought it was about time to show how we can debug CA’s. Before DTF it was almost impossible to step into your code written in C++, VB Script or Java Script and debug. With DTF this is simple, but still not 100% intuitive or straight forward. You have two options mentioned in the DTF documentation for debugging your code and a third which is not mentioned:
- Use environment variable MMsiBreak (not to be confused with MsiBreak)
- Attach the debugger to the process via a message box
- Use System.Diagnostics.Debugger.Launch
Here’s how to add MMsiBreak to your environment variables in Vista:
- Start –> Right click Computer –> Properties (or navigate to Control Panel –> System)
- Select Advanced system settings
- Click Environment Variables…
- In the System variables section click New…
- Set Variable name = MMsiBreak
- Set Variable value = Name of your custom action method
On my computer it looks like this:
In my example it will break for debugging when Windows Installer is executing the CA GetWebSites. When that happens you will get the following dialog:
Select Yes and you will be prompted to select a debugger to use. If you already have your solution open in VS, you will get the option of using that. Note however that on Vista admin privileges is required, so you need to have your Visual Studio running as admin in order for it to bee listed in the below screen:
When I select the running VS (as above I’ve done above) I get something in VS which I can’t quite explain. The first time this happened to me I thought it didn’t work. I get this message:
The thing is that the source code is of course already displayed, but I thought there was some problems with loading the symbols. However, if you just click Ok and hit F5 (Start debugging) in VS, your breakpoint will hit. Just a thing to be aware of if you get this.
Using Message Box
By using a message box you can accomplish the same thing, but this requires changes to your code and a recompile of both your CA project and you WiX project. Personally I prefer the above method, but it’s always nice to have options :-)
In order to debug using message box you must:
- Make sure you have a reference to System.Windows.Forms.dll.
- Somewhere in your code (where you want to break) add some code for displaying your message box. Something like this:
MessageBox.Show("Please attach a debugger.");
- Add a breakpoint somewhere in your code below your message box code
- Rebuild your CA project as well as you WiX project to get the new changes.
- Run your MSI.
- When the message box displays, go to Tools –> Attach to Process… (Ctrl + Alt + P)
- Find the process named rundll32.exe and attach.
- Click Ok on the message box in you installation.
- The breakpoint you set earlier should now be activated in VS
This is exactly the same as using MMsiBreak except you trigger it from code instead of a environment variable. Just add this line to your code where you want to debug:
This will give you the same “Unhandled exception” dialog as before and the rest is the same.
The MSI log file
If you’ve been working with MSI’s you know this already, but I think this is something every developer/it-expert should know about and in my experience most people don’t. Sometimes when you run an MSI and get an error that maybe causes a rollback and you can’t get the installation to install, you’re stuck with a cryptic error message. If you’re lucky you can Google it and maybe find the problem (or solution), but often this is not the case. Then this little command might come in handy:
msiexec /i NameOfMSI.msi /l*v C:\Temp\install.log
The above command uses msiexec.exe which is what Windows uses when you double click on an msi. Actually Windows does exactly like the above except from the /l*v part and that’s where you tell msiexec to log to a file. Here’s what it means:
/l = Log
* = Everything
v = Verbose
You can skip the v and you will get slightly smaller log file. Personally I use v all the time.