Edit:
As an aside, as much as I appreciate the work Acresso did on Managed CA's, DTF is a better direction to go.
1) It solves the problem of tatooing the msi process with a fixed version of the CLR
2) It's linker ( MakeSfxCa ) is more flexible for including dependencies an
3) The interop is simply better
4) The hosting process has a better debugging story
5) It's open source so it's easier to see problems and get resolutions to issues
6) It's not tied to one vendors authoring tools
In previous posts I've discussed the use of the InstallScript function CoCreateObjectDotNet()to include Managed Code in your InstallScript custom actions without any installation or registration of .NET assemblies. Still this had the downside of having to write InstallScript CA's to act as a wrappers for your managed assembly. This increased the complexity of the solution and added slightly to the package size and execution latency.
In late 2006 I had an email discussion with Robert Dickau where I suggested the possibility of supporting managed code CA's directly similar to the way InstallShield already has support for non Type1 DLL function exports via the "New Standard DLL" pattern. I also suggested that it would be good if they could support passing the MSI handle and providing a simple C# SDK that included a basic MSI interop.
While I'm not sure if I really inspired the next feature or if it's just a case of great minds think alike ( except for certain great minds who seem hell bent on denying the fact that managed code is the future of windows development), InstallShield development has once again jumped in with some really cool stuff:
Support for Managed-Code Custom Actions
InstallShield lets you add managed-code custom actions to Basic MSI, InstallScript MSI, Merge Module, and Web projects. This type of custom action calls a public method in a .NET assembly that is written in managed code such as Visual Basic .NET or C#.
Ok, that doesn't really give it justice. Let me show you a simple example. Let's say you are writing a VSTO 3.0 Installer and you need a random number to write to the Office 2007 Count Registry Value. You could break out a C++ compiler and track down a standard library for generating a random number and build it as a MSI Type 1 DLL CA, but the odds are increasing every day that your team doesn't have those obsolete skills anymore but instead is getting really good at writing managed code in C# or maybe VB.NET. Since you are deploying a VSTO installer you already have a dependency on the framework so why not just put the BCL to work for you?
Consider this simple code fragment:
Now let's wire it up into InstallShield 2009:
We browse to the DLL ( Just like other CA types ):
Now here is where it gets a little cooler. With standard DLL's you have to export them as stdcall and use Depends to confirm the function name. With CoCreateObjectDotNet() the assembly has to be attributed as ComVisible(true). However, with the new pattern you don't need ComVisible and InstallShield uses reflection to help you complete the contract:
Now let's assign the return code to a public property:
Finally, let's schedule it in the sequences:
Finally, let's just display it on the welcome dialog so we can see it works:
That's pretty much all there is to it. You may have noticed that I scheduled the CA in both the Install UI and Install Execute sequences and set it to only execute once. This means I'll have to add the public property to SecureCustomProperties if I expect the data to persist during UAC/Elevated/Managed full UI installs. Otherwise I'm ready to use this property in the Registry table as [RANDOMNUMBER].
If you are curious how it works, you'll have to download the beta. Take a look at the CustomAction and ISClrWrap tables.
BTW there is also the possibility of using a "standard signature" which allows passing the MSI handle. There is rumors that Beta 2 will have an interop included so I'll have to show how that pattern would work at a later date.
Oh man, that's awesome. I am going to have to download the beta and give this a whirl.
ReplyDeleteOUTSTANDING! I've been putting off learning C because I feel managed code is the future. Now, if only the MSI team would get their act together and support this natively.
ReplyDeleteC/C++ is still a good skill to have, even if in the narrow focus of the Windows Installer realm. But yeah...
ReplyDeletefoo = Session.Property("BAR")
...is certainly a lot simpler than:
TCHAR* szPropBuf = NULL;
DWORD cchPropBuf = 0;
UINT uiRet = MsiGetProperty(hInstall, TEXT("MYPROP"), TEXT(""), &cchPropBuf);
if (uiRet == ERROR_MORE_DATA)
{
++cchPropBuf;
szPropBuf = new TCHAR[cchPropBuf];
if (szPropBuf)
{
uiRet = MsiGetProperty(hInstall, TEXT("MYPROP"), szPropBuf, &cchPropBuf);
}
}
if (uiRet != ERROR_SUCCESS)
{
if (szPropBuf != NULL)
delete [] szPropBuf;
wsprintf (msg, L"Error retrieving the MYPROP property: %s", uiRet);
LogMessage(hInstall, msg);
return ERROR_INSTALL_FAILURE;
}
I did learn ( and actually use once upon a time ) ANSI C back in the 90's. Pointers are fun, and important to understand, but for Windows development even Rob has to notice that you can now get hired at Microsoft without being able to write C/C++.
ReplyDeleteI once read an article about a pure managed code prototype operating system and I've even had wierd dreams about hardware that emulates the VM so that IL becomes the new Assembly.
Singularity ( http://research.microsoft.com/os/Singularity/ ) is pretty close to what you were talking about.
ReplyDeleteYes, that's exactly what I was referring to. There is an interesting video on it over at http://channel9.msdn.com/ShowPost.aspx?PostID=68302
ReplyDelete
ReplyDeleteI once read an article about a pure managed code prototype operating system and I've even had wierd dreams about hardware that emulates the VM so that IL becomes the new Assembly.
He he. Yeah. I had the same dreams many years ago when Sun announced the JavaOS and the Sun JavaStations. Very sad that it died a horrible crib death. Could have been insanely great ;-)