-
There are some problems using older .wixproj files with newer builds of Votive. When accessing project properties you may receive the error message:
An error occurred trying to load the page.
Value does not fall within the expected range.
Update: As another symptom of the same issue, you may also experience problems with source control check-out with any projects in the solution.
The breaking changes were introduced in WiX builds 3.0.4109 - 3.0.4220, so a .wixproj created with a build <4109 will have problems when used with a build >=4220. I'll explain the changes here and show you how to update older project files to work with newer WiX builds.
The changes are all about the default and available platform configurations of WiX projects. Previously, WiX projects always had a platform of "Any CPU", and there was no way to change it. But actually MSI packages are somewhat platform-specific: a package is marked as either 32bit or 64bit, and cannot be both. While a 32bit MSI can install on a 64bit OS, it's a bit like a 32bit EXE running on WoW in that it can't easily interact with any of the 64bit parts of the system.
The WiX command-line toolset has long enabled building both 32bit and 64bit MSIs, and more developers are starting to build 64bit packages, so we thought it made a lot of sense to expose that capability in the natural Visual Studio representation: project platforms. With the latest builds, a new WiX project has its configuration set to "x86" by default, and you can use the VS Configuration Manager to add an additional "x64" platform if you need it. (IA64 support is not yet implemented... is there any demand?) Also "Any CPU" is no longer a valid platform for WiX projects -- it was only there because Votive builds on a VS project framework was originally designed for compiling .NET languages.
If you have WiX projects that were created with an older WiX build and you want to continue to use them with a newer build without recreating the projects, use the following steps:
- Install the new build of WiX.
- In VS, open the solution that includes one or more WiX projects.
- For each WiX project node in the solution explorer, right-click and Unload Project, then right-click again and Edit the .wixproj.
- Change the conditional expression on each configuration PropertyGroup to include an "x86" platform:
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
...
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
- Right-click on the project node and Reload the project.
- From the Build menu, open the Configuration Manager tool. Ensure that each WiX project is selected to build (if desired) for each solution configuration.
-
New in this week's WiX build 3.0.4123 are Visual Studio 2005 & 2008 templates for C++, C#, and VB custom action projects:

The C++ project sets you up with the WiX unmanaged CA utility library (wcautil), while the C# and VB projects use the DTF library for managed-code MSI custom actions. I assume you're here because you want to read more about the latter.
When DTF first released with WiX last week, it included some sparse documentation about how to create a post-build step to package up your managed CA assembly in a form callable by MSI. I apologize to anyone who jumped on it right away and had trouble hooking things up (which was only made more difficult by a missing binary that had to be built from source). I should have had these templates ready then.
When you create a C# custom action project from the new template, the project has the necessary post-build step hooked up already. For the curious, those build rules are in %ProgramFiles%\MSBuild\Microsoft\WiX\v3.0\wix.ca.targets. Building the custom action project will produce an additional DLL in the target directory with the name $(TargetName).CA.dll. That is the DLL to be streamed into your MSI Binary table. Since that DLL exports ordinary entrypoints callable directly by the MSI engine, you can use it with any MSI authoring tool as if it was an unmanaged CA DLL.
The custom action build process will automatically package up any non-GAC'd assemblies that your CA depends on. (Make sure the Copy Local property is set to 'true' on the reference node if you want it included.) Those dependencies will include at a minimum the Microsoft.Deployment.WindowsInstaller.dll assembly from DTF. Additionally, any items in the project with a Build Action of 'Content' will be included in the CA package. CustomAction.config is the sole Content file in the template; your CA may require additional resources or data files at runtime.
In Votive, a convenient way to consume the custom action DLL in your setup is via a project reference:
- Create a solution with a WiX MSI or WiX Library project and a C# or VB custom action project.
- Add a reference from the WiX project to the custom action project.
- Author the custom action in your setup with WiX code similar to the fragment below. Note you may need to change some attributes in the XML, depending on your CA and how it executes.
<Fragment>
<Binary Id="MyCustomAction.dll"
SourceFile="$(var.CAProjectName.TargetDir)$(var.CAProjectName.TargetName).CA.dll" />
<CustomAction Id="MyCustomAction" BinaryKey="MyCustomAction.dll"
DllEntry="CAMethodName" Execute="immediate" />
</Fragment>
I hope this helps interested developers get started with managed custom actions. Future posts here will hopefully get into some actual coding.
-
Rob mentioned in this morning's announcement that I've been working on the DTF project for quite a while. Indeed, if you look at the change history topic in DTF.chm, you'll see entries going back to January 2003. (And development of what would become DTF actually started over a year prior, when .NET 1.0 was not quite released yet.) Before I get into some technical topics, I wanted to talk about how the project evolved, and maybe explain a bit about why it took so long to get released externally.
As I said in my introduction, in previous years I spent a lot of time working on internal deployment-related tools. Specifically these were tools for authoring, building, installing, testing and debugging MSIs and MSPs for DevDiv products, mostly Visual Studio and .NET Framework. I found very early that programming against the Windows Installer APIs in C++ is a slow and sometimes arduous task, and while script is easier to write it's not a robust scalable solution. I wanted to take advantage of the great productivity gains of the then-new .NET platform, so I started by creating a limited interop library for accessing the MSI APIs from a .NET language. As I worked on more tools, I gradually filled out and improved that interop library. I also added a cabinet library since working with MSI setups often involves dealing with cabinets.
After sharing it with a few other teams in the company who were also working on deployment related tools, I got great feedback on the value of the project, which motivated me to cover the remaining MSI APIs and add more documentation to make it a more complete framework. Most of this work was actually done outside of my day job -- I would work a few evenings and weekends on the project now and then, just motivated by the positive feedback and knowing that I was making other developers' jobs easier.
The debate about managed custom actions is nearly as old as managed code. While the .NET Framework has always provided an InstallUtil tool that lets you invoke managed assembly Installer classes during the setup, it is, to be blunt, a managed version of self-reg suffering from nearly all the problems that plague classic DLL self-registration. That means InstallUtil custom actions usually are not a good idea if you're interested in creating a really clean and robust setup. Still, if you're working with a product or platform that's all based on managed code, it's likely your setup will need to run managed code to intract with it.
So with the DTF project I took on the challenge of enabling real managed custom actions that have all the capabilities of unmanaged custom actions in terms of access to the installer session, allowing them to follow the best practices for data-driven custom actions. Given that I already had a library that exposed all the MSI APIs in managed code, I was halfway there, or so I thought. Over the years I went through three major design iterations for how the managed-code CA got launched. While the earlier designs seemed to work well, they suffered from some subtle robustness issues related to interactions between the CLR and the MSI engine. It wasn't until last summer that I finally overcame the last technical hurdle (described in Rob's blog post) to achieve what I believe now is a robust framework for managed custom actions.
For several years I've been looking for a way to release the DTF project externally, since I think there are lots of developers who would find it useful. There have been a number of reasons why it didn't happen until now. For a while the MSI team was hinting that they might implement their own set of official managed APIs for the Windows Installer platform (and I didn't want to cause confusion with an alternative), but now it doesn't look like that will happen anytime soon if ever. Also I didn't want to release a framework for managed custom actions until I had something that addressed robustness issues with CLR and MSI interactions.
The final barrier to releasing DTF was the strategic concern, also described by Rob, about wanting to reduce people's reliance on custom actions in their setups. Personally on this issue I've always been somewhat of a pragmatist: the MSI platform can never support everything that people might possibly need to do in their setups, so there will always be a need for some custom actions. And if my framework can make it easier for those people to write quality custom actions, I think that's a good thing. Now that a few other key people here have more or less come around to that point of view, DTF could finally be released. I hope all the developers out there will prove us right by not writing too many crazy ill-conceived managed custom actions.
-
Today's release of DTF with the WiX toolset has finally given me the motivation to start this blog, which I have long intended to do anway. Before I delve into posts about DTF, I thought I would share a little about myself.
I've been a developer at Microsoft for about 8 years now, and have spent most of that time working on various areas of software deployment. For a long time it was primarily internal tools, which is why you haven't seen much of me out here. More recently I've become the lead for a team in the Deployment Technology Group in DevDiv responsible for integrating WiX and Votive into the next release of Visual Studio. This means I've been working closely with others you may know in the WiX community including Rob, Justin, Bob, Peter, and Heath.
In addition to software deployment, I'm passionate about managed code and developer tools, so I spend a lot of time working on the intersection of those thre areas. This passion has led directly to my work on the DTF project, which I am excited to talk about in upcoming blog posts.