At my next job I saw exactly how ugly Installer Class custom actions were. For awhile I bought into the `managed code custom actions are evil` hype that is constantly repeated by the same three or four people. Then my new manager announced that I'd be spending a week learning C#/.NET 2.0. For the life of me I really couldn't understand why I was going to spend a week learning .NET. After all, what possible place could managed code have in Setup after the hell I had just witnessed? In my mind the future was unmanaged Type 1 CA's written in InstallScript since C++ is just pure hell. I even had an expert C++/C# developer validate that opinion for me.
So I went off and I learned C#/.NET 2.0. Wow, it rocks. Once I really understood it, I came to realize that it could be easily and safely used as a platform for custom actions in MSI. Frankly, C# makes horrific things in C++ look like childs' play. Take this little quote from the WiX-Users list that I recently read:
I realise that [not using managed code] leaves you with few options, since as far as I can see
the web service is the supported API for doing this. Normally for custom
actions we recommend using unmanaged C++, but web services aren't at all
easy to use from C++.
Last September I started another job ( I know... I move around a lot ) and I wanted to implement a pattern that took user input and connected to a server to validate the data. I quickly wrote a C# class in VS2003 that was exposed as ComVisible(true) and exposed an interface for passing data to a webservice and returning the result. Then I wired this up using InstallShields CoCreateObjectDotNet() function. This function basically allows invoking ComVisble .NET classes through reflection without actually having to register the COM for interop.
In the countless times this install has been run, I have never seen or heard of this custom action failing, period. Sure, now I have to deploy a .NET framework, but I did anyways because our software requires it.
Now I've also heard the argument that our CA could fail one day in the future on a newer version of the .NET framework. After all, in the COM->.NET story the latest version of the CLR is used. When I started this story our application was written in .NET 1.1 and later ported to .NET 2.0 and tested on Vista with .NET 3.0 ( CLR 2.0 ). My CA was built using .NET 1.1 and I've never rebuilt it for 2.0. It just works as is on 2.0.
The only advantage that I could give C++ in this story would be faster instantiation and less memory usage. I won't agree that C++ is any more reliable then C#. In fact I would say that unless you have a very experienced C++ developer who will make sure that all errors are handled and memory properly allocated, free'd and buffers protected from overruns, that C++ could actually be less reliable then C#. I'd also say that unless the forementioned person worked in some third world company for dirt cheap that writing the code in C++ would be more costly then writing it in C#.
So if you have similar needs, I encourage you to explore managed code and not buy into the `managed code is evil and doesn't belong in setup` myth.
We experienced some problems with managed code custom actions, but it has to do more with InstallScript's CoCreateObjectDotNet than anything else. When that doesn't work, we simply write a managed executable to do what we want.
ReplyDeleteCoCreateObjectDotNet seems to have problems with .NET wrappers of some Win32 DLLs. I was getting weird exceptions that only manifested themselves when called from InstallScript. Macrovision support was entirely useless on this occasion.
Have you created a thread over on Community? I'd love to investigate this if you could provider your wrappers.
ReplyDeleteI'll create a post over there, but unfortunately it will only be snippets. The main DLLs causing me problems are licensed and I can't really post them.
ReplyDelete