I was recently pinged by a triumvirate of individuals asking me about using managed code to write CustomActions. This is a hot topic that comes up about every other month on the wix-users mailing list at SourceForge. Those of you that hang out on that mailing list know that I've repeatedly stated that the WiX toolset does not support managed code CustomActions because the Windows Installer team does not support managed code CustomActions.
However, since I was asked by three people (all of them knowledgeable and respectable) at the same time I thought I would again ask the Windows Installer team about supporting managed code CustomActions. I got the same answer I got last time, "The Windows Installer does not support CustomActions written in managed code." However, this time we had time to have a deeper conversation about why the managed code is not supported for CustomActions. There are essentially two reasons managed code is not supported: one technical, one strategic.
Technical
The technical issue that managed code CustomActions have is due to the fact that the .NET Framework is "sticky" (Carolyn, MSI Dev Lead, used the phrase "tattoos your process"). Once you load a version of the .NET Framework into a process, the .NET Framework is not unloaded. More importantly, if you attempt to load a different version of the .NET Framework into your process later you will get the previously loaded version.
I have to admit this technical issue with using managed code in CustomActions surprised me. I had heard of the problem before (of course, Carolyn had mentioned it a few times) but I didn't truly understand the ramifications until I wrote the code tonight then stepped through it in the debugger. It is kinda' cool to see the .NET Framework v1.1 get loaded by one CustomAction then later have a second CustomAction try to load the .NET Framework v2.0, get the v1.1 Framework handed to it, then fail when trying to create an app domain later. Well, it's only cool because I anticipated the failure.
What this mean is that if you end up in a scenario where you have a CustomAction written for one version of the .NET Framework and a second CustomAction written for a different version of the .NET Framework that your second CustomAction will fail before it can even get started. Well, you could mark your .NET Framework 1.1 CustomAction to say that it will run in the .NET Framework 2.0 and then try to ensure that the .NET Framework 2.0 is loaded everywhere. That might work until there is another .NET Framework version (4.0?).
There is additional complication on Windows Server 2003. On that OS, the Windows Installer will attempt to load the .NET Framework 1.1 into the deferred CustomAction server (for a reason that Carolyn mentioned but I've forgotten now, should have taken better notes). If you have already loaded the .NET Framework 2.0 (say, for a CustomAction) then the Windows Installer can fail to add files to the Global Assembly Cache.
All of these complications when managed code CustomActions are introduced reduce the chances that an installation package will successfully install and uninstall (let alone upgrade or be patchable). When you approach the problem from a platform point of view (as the Windows Installer team must), I hope you agree that there are way too many common failure cases to support managed code CustomActions.
Now the intrepid developer might suggest that managed code CustomActions could be hosted in a separate process from the Windows Installer's CustomAction server. That way the separate process would disappear and take the .NET Framework with it each time the CustomAction exited. Make no mistake, this solution takes a lot of work and is most likely something along the lines of what the Windows Installer team would need to do to support managed code CustomActions.
However, they are focusing on other features because of their strategic position on CustomActions.
Strategic
Inside Windows there is a fair bit of discussion going on right now about how to improve application deployment on the operating system. Knowing about the discussions, I invited a couple of the Windows architects to my conversation with the Windows Installer team about managed code CustomActions. My hope was to provide the architects with a couple real world examples of problems facing setup developers today and maybe get some insight from them along the way. What I got was validation of something I've seen coming for a long while.
Strategically the goal is to reduce the number of CustomActions shipping in installation packages. It is generally accepted that a great majority of the installation failures out there today are failures inside CustomActions. CustomActions in installation packages also surface as major problem for application compatibility between operating systems. The data collected thus far suggests that application deployment would be improved by reducing the number CustomActions in installation packages.
Making it easier to create more CustomActions (which a managed code for CustomAction would certainly do) does not align with the strategic goal.
Now, having written something like 75% of the CustomActions in the WiX toolset let me assure you that I'm one of the first to point out that CustomActions are quite often a necessity today. However, I also know that the code in the Windows Installer has had far more scrutiny and testing than the WiX CustomActions to date. Thus, I can agree that it would be better if there were fewer CustomActions shipping in installation packages today and that the installation functionality was instead built into the Windows Installer or the operating system in general.
For example, imagine that to configure a web site in IIS that you didn't need a CustomAction from the WiX toolset (or some other vendor). Instead, you just declare that you want your web site (much like you do in the WiX toolset today) and code that was installed with IIS would be activated by the Windows Installer to do the work. That means that you and I would not be responsible for reverse engineering the IIS store (i.e. the metabase) then writing the CustomAction to ship in our installation package. That would move us all a great many steps away from CustomActions and hopefully towards a more stable operating system.
Now, I know there are a good number of other things that people use CustomActions for today. I also know that it would be very convenient to be able to write CustomActions in managed code. However, today the Windows Installer does not support managed code CustomActions and the general direction appears to be to try to reduce the need for CustomActions overall.
RobMensching.com LLC
37 Comments
Comment by Kenneth Bell on Thursday, April 19, 2007 3:09 AM
There are other ways to acheive this, such as performing app-specific 'upgrade' logic on first use - but consider unattended installs, and similar scenarios.
Reducing the need to write custom actions is great, but there is a risk it will be used as a reason for not providing the support that app vendors need.
Comment by Anonymous Coward on Thursday, April 19, 2007 5:42 AM
Comment by Christopher Painter on Thursday, April 19, 2007 6:47 AM
Unfortunately I've lost confidence that the Windows Installer team will get this job done. The last generally available release of MSI isn't available down-level and only adds stories related to Vista UAC/RM functionality. Cool stuff, but not the additional standard action patterns that many people have been begging for over the last several years. The release before that seemed to focus mainly on patching. Even if the Windows Installer team was to pull a rabbit out of the hat and support these stories, I doubt they would port it down-level to a 3.x branch.
Please, tell me I'm wrong with that assessment. Please tell me that Bill G is going to throw so money at that team and we are going to get the framework improvements we have all been begging for.
Until that day comes, Custom Actions aren't only tactical; they are strategic because there is no other viable solution. You raise some interesting points about AppDomains and the CLR and yet I've seen InstallShield address these issues with their CoCreateObjectDotNet() pattern. I've also done some work on my own with .NET 2.0 IPC remoting and I've found it to be a very reliable way of hosting custom actions out of process and yet still giving them the ability to communicate with MSI.
For the rest of Microsoft, managed code is clearly marketed as the future of software development. Windows Installer should adopt this strategic initiative and simply overcome the technical hurdles. This way we can have really good custom action patterns to play with until the day comes that MSI natively supports the patterns that we are writing custom actions for. Then we can gladly dump our CA's and refactor using the built-in standard actions.
Comment by Michael Urman on Thursday, April 19, 2007 8:44 AM
If we are not going to see built in patterns, whether it's because something Windows Installer does only on 2003 can conflict, or because the team just hasn't gotten to it yet, we all need more documentation of the sort you just posted here so when we tackle a technical problem, we can weigh the tradeoffs. Thanks for sharing this gem.
Comment by Nathan Stohlmann on Thursday, April 19, 2007 9:06 AM
Comment by John Vottero on Thursday, April 19, 2007 9:16 AM
I have no desire to create managed custom actions, I want to be able to use the managed custom actions that Microsoft is releasing. What's the best way to register a PowerShell snap-in, call the managed code produced by the PowerShell team or reverse engineer that code so I can do it without the managed code?
It was particularly galling to read that the Windows Installer team's strategic direction is exactly what I want to do, let the PowerShell (or IIS or MMC) team write the code that does the right thing during installation. Most (maybe all) of those teams are writing managed custom actions.
Comment by Peter Thomas on Thursday, April 19, 2007 10:19 AM
Saying, and please excuse the paraphrasing, that “CAs cause the majority of failures so we want to make it hard to make CAs” just doesn’t make any sense. CAs were created to provide a way for installation developers to perform tasks that the Windows Installer team didn’t implement or couldn’t. The need for CAs will never change. Installation developers will always have requirements unique to their applications. When they have to write those CAs, does it support the Windows Installer team’s goal to have more stable installs for the installation developers to write their CAs in managed or unmanaged code?
If the concern is that installation developers will write CAs instead of utilizing the built in tables (when available) than that is an education problem and not a reason not to bring CAs into the present.
Comment by Neil Sleightholm on Thursday, April 19, 2007 10:44 AM
Comment by Christopher Painter on Thursday, April 19, 2007 12:10 PM
<parody>
In other news, Microsoft announced today that future versions of MS-DOS will never support more then 640K of conventional memory. The tactical reason given was that protected mode memory remapping was too unreliable and difficult to do correctly. Besides, developers will never need more then 640K of memory.`
</parody>
Comment by Albert on Friday, April 20, 2007 6:01 AM
Comment by Joe Kaplan on Friday, April 20, 2007 10:49 AM
- The technical limitations can be overcome as you suggested and Christopher seems to have already built
- The strategy appears to be broken, as they are basically saying "CA's are unstable, so we'd like to discourage their use in general, but we you will need to wait for a future MS OS (4+ years for relase!) to make the need for these CAs go away." How does that help anyone get work done for the next decade!?
- Managed CAs could potentially offer some advantages for cross-OS compat as they offer an abstraction layer over the OS.
- Managed code is also an important part of the strategy for coding on the Windows platform, so why shouldn't set up be part of that strategy?
- A good technical implementation and guidance on how to use managed CA's effectively (transactional, table driven, etc.) would probably do more to address the needs of setup developers now and would produce far better set up results for the next 5 years or so while this more far reaching strategy comes to fruition.
Comment by Kevin Dente on Friday, April 20, 2007 11:30 AM
>v1.1 get loaded by one CustomAction...
In the COM interop world, the latest version of the Framework that's installed always gets loaded. Why wouldn't the MSI world work the same? Yes, there's still the possibility that the newer version of the framework is incompatible with the older version, but MS works pretty darn hard to avoid that (sometimes too hard).
I agree with the other comments here. Saying that custom actions shouldn't be required is really just sticking your heads in the sand. There will always be the need for application specific install actions - MS can only deliver platform specific install actions. And with more stuff out of Redmond moving toward managed APIs only, even that will eventually run out of steam.
Comment by Heath Stewart on Friday, April 20, 2007 7:17 PM
The point is that many people don't need to write CAs if they look for standard actions or existing, well-written CAs like those found in WiX and often commercial packages or other community sites like http://installsite.org.
Take, for example, application configuration data as the first comment states. Instead of treating the whole file as a resource, treat its contents. The XmlConfig CAs in WiX make operations on the content-level possible with XML files. Windows Installer supports INI (and INF) files through the standard IniFile table. If you have some proprietary format, you might consider the affect of that on users and switch to a more common format. If a common format doesn't already have a CA for editing the content, then a community contribution or requested CA should be created. There's no reason everyone should write their own CA to do the same thing with various levels of quality.
Comment by Dhaval Patel on Monday, April 23, 2007 10:39 PM
It seems that the deployment section of the prodcut development cycle is the last thing on MS's "to do" list.
Thanks to Rob, the folks on WIX, and the current MSI team for all the great efforts they have put into this... I just wish the folks at the top would take more interest.
Comment by MrMike on Tuesday, April 24, 2007 11:45 AM
The install process needs to be as simple and clean as possible. If an installer requires a considerable amount of code to configure the target system, then one should consider moving this code out of the installer and into the application.
I really don't understand how people can make a case for managed CA when the state of managed code and .NET is still in flux. Perhaps sometime in the future, but as it stands right now... no way.
Comment by Phil Wilson on Tuesday, April 24, 2007 1:43 PM
Comment by Phil Wilson on Tuesday, April 24, 2007 1:48 PM
The issue is here is really about the infrastructure for calling user code during an install, and that the MSI infrastructure for this (custom actions, including managed code custom actions) is not a good fit for a lot of the things that people use them for. The strategy is moving towards having this code outside the MSI file. What's needed is a launching infrastructure that (say) creates AppDomains, calls assemblies, runs programs, launches the MSI, runs post install stuff etc, with some corresponding rollback.
Comment by Christopher Painter on Thursday, April 26, 2007 12:47 AM
Recently I did an install for MySQL which was a major pain because not only did the install have no points of variation for configuration, but it also didn't provide any automation layer ( that I could find reference to ) to configure the instance. The configuration wizard that set up the instance was GUI only. This made it very difficult to try to deploy MSSQL as an embedded private instance .... something that is VERY easy to do with MSDE because the package natively handles the configuration requirements.
Comment by AJ on Saturday, April 28, 2007 1:12 PM
As far as I am concerned, Windows Installer has reached it's end of usefulness for ISV-based installations. The only real advantage of a pure MSI file is for repackaging legacy applications for deployment.
It makes no sense to use Windows Installer when there are more custom actions than standard actions (ahem...Office team). Hence, why I have moved to the C# wrapper that performs all the configuration tasks while maintaining a pristine, (custom action)less Windows Installer package.
The least the Windows Installer team could do is provide a supported .NET interop assembly. PLEASE!!!!
Comment by AJ on Saturday, April 28, 2007 1:21 PM
On the sticky .NET issue. Did anyone else stop to think that JUST MAYBE my custom actions and my installer project would be in the same solution...AND...get this, built on the same version of the .NET Framework?
I know it sounds revolutionary and all, but there are some people out there that actually code like this. I know, crazy right?
</sarcasm>
Comment by Daniel Steiner on Tuesday, May 15, 2007 4:33 AM
Comment by Rachna on Tuesday, September 11, 2007 11:43 AM
I was on a team until last month where in the setup had more than 10 custom actions to do stupid things like showing custom messages and writing to log files. The setup was meant for installing an SDK which consisted of 1 binary and 4 tools binaries...that too free...and took longer than most other setup's.
IMO there should be a company wide rule to develop custom actions in unmanaged code only, there by improving the quality of setups overall
Comment by Daniel Steiner on Saturday, October 06, 2007 10:45 AM
not everybody you see here on the list for the first time have to been a newbie.
Speaking for my person I've more than 20 years experience with MS technologies starting with MS-DOS 2.x Int21h programming, Windows 2.11 assembler/pascal/c SDK etc. and have a rather good knowledge and understanding of MS technologies.
Coming back to the topic of this blog, there are some real and good reason why to have managed custom actions:
- smaller package than native code
- tested and stable code .NET Framework
- more flexible what you can do due to large BCL
- less coding by using BCL resp. C# programming language compared to native C++
- verifiable and digital signing of assembly
- cross plattform, you need only a single binary not for each plattform(IA32,x64,Itanium, etc.)
- you can use compiler you want especially you don't need to include some runtime libraries depending on you compiler.
eg. when using VC2005 you need to include runtime as it's not guaranteed to be present on the target system.
You can argue the same way for using managed code in SQL Server 2005 and nobody is asking why do we need it - we've already T-SQL and C++ native commands :-)
Comment by dB. on Thursday, October 11, 2007 6:14 AM
In my real world I need to write a CA and would like to write it in managed code. I have a bunch of small MSIs and I don't have CAs in different .NET framework versions so this isn't a problem. I have nothing to put in the GAC.
So this is for the least frustrating. Especially that I've used MsiManaged from MSFT toolbox before and several internal (and possibly external) Microsoft projects use that as well and very successfuly. Just ship that with all the notes and warnings.
Comment by Mike Smith-Lonergan on Tuesday, December 04, 2007 9:53 AM
It's too bad that there was no product revenue at stake to be tied back to the Windows Installer team - perhaps then they'd worry more about solving customers' problems *today* and have less of the laissez-faire attitude of "we'll do it right, but only for future versions of Windows, and we don't care about the 'legacy' problems."
The *smart* response to the problem of too many Custom Actions creating too many compat issues is to build clear, actionable, step-by-step guidance/examples/templates that accommodate the customers' actual deployment scenarios, rather than living in the fantasy that the few scenarios that were built in to the product "should be sufficient for everyone, if they're 'smart' about it."
Grrr...
Comment by Oladipo Olasemo on Monday, February 11, 2008 7:30 AM
Comment by Christopher Painter on Thursday, March 20, 2008 4:23 AM
Comment by laughingskeptic on Monday, October 27, 2008 12:56 PM
Comment by Shaffer on Friday, November 07, 2008 8:35 AM
I like the data-driven approach of MSI, but
if you have only .NET code, a script (PowerShell, WSH, whatever) that calls InstallUtil.exe with the "install logic" being in .NET installer classes starts to look like a better option than MSI for some. Having a common install engine is helpful to the Windows platform, but only if people use it. And people won't keep using MSI (or use it to copy files) if its significantly more work to do so.
From the outside this does seem petty squabble at MS between the MSI team and the .NET "xcopy/InstallUtil" folks which isn't helpful to ISVs/customers. It would at least be nice for clarity from MS on the path for developers that have only managed code to install...
Comment by andy on Saturday, January 24, 2009 1:49 AM
Comment by Steven Bone on Monday, November 09, 2009 12:03 PM
Comment by Rob Mensching on Tuesday, November 10, 2009 3:29 PM
Comment by David on Thursday, July 01, 2010 12:54 AM
If custom actions in managed code are not supported in WiX, why does Votive (created by the same team) have C# and VB Custom Action Project templates? And I can't imagine that this is the only place where Votive and/or WiX exposes managed code CA functionality.
Comment by Rob Mensching on Saturday, July 03, 2010 11:43 AM
Comment by FCM on Wednesday, September 08, 2010 9:53 PM
Comment by Rob Mensching on Thursday, September 09, 2010 10:20 AM
Comment by Vadim Rapp on Friday, October 01, 2010 5:49 AM
I'm curious though, with this lack of support being an obvious glaring hole, was/is there any movement in Microsoft to fixing it? one might think that this might be a priority when developing Installer 5 and .Net 4....