Friday, June 27, 2014
I was troubleshooting an installer today when I came across what I consider to be a bug in Windows Installer's DTF managed custom action pattern. First a little backstory: WiX DTF Managed Custom Action projects allow you to add project items as content. During the build this all gets packed into a self extracting custom action that then gets stored in the Binary table of your MSM/MSI. At runtime the binary is extracted to an MSI determined temp directory and a native hook is invoked. This native code then extracts the contents of the self extracting CA into another temp directory and then launches a routine that eventually results in your managed code running. It also sets the current directory of the process to this temp directory so that your content resources can be referenced. That's how it's supposed to work. Or at least that's how it's always worked. The WiX team doesn't really document this so I'm sure the "functions as designed" or "functions as coded" door is cracked slightly open. Ok, so the behavior I want to alert you in is if the Microsoft.Deployment.WindowsInstaller.dll (interop library that DTF uses to marshal MSI API calls to the custom action) is in the GAC the current directory won't be the temp directory as expected, it'll be the directory in the GAC (C:\windows\assembly\GAC_MSIL\Microsoft....) that the assembly is stored in. This means any relative path references to your content files will now fail. Ok, so how do you protect yourself? Add this line to the beginning of your custom action: Environment.CurrentDirectory = new FileInfo(Assembly.GetExecutingAssembly().Location).Directory.FullName; This will ensure that the current directory is set to the directory that your assembly was extracted to. I believe this is the first DTF bug I've seen in about 3 years. The last was a race condition fixed in 3.6 or 3.5 that randomly prevented a CA from firing. The only before that was back around 2008 and involved custom action sandboxes being recycled and previous custom actions changing the current directory to a directory you wasn't expecting. I believe it was back then that DTF added a current directory initialization pattern and it generally works well except for the gotcha I just noticed. Update 6/28/2014: Just one day after reporting the bug, Sean Hall has submitted a pull request and the issue has been marked as fixed for WiX 3.9. I'm not sure when 3.9 is going to ship but I'm very thankful and impressed with how quickly this bug was addressed. Thanks guys!