ISWIX, LLC View Christopher Painter's profile on LinkedIn profile for Christopher Painter at Stack Overflow, Q&A for professional and enthusiast programmers

January 22, 2008


I'm working on an install that requires me to write some custom actions to interact with the certificate stores. I seems there are four different ways to do it out there:

certmgr.exe : The way the developer suggests doing it. Of course it's a .NET SDK utility with redist rights.
cryptoAPI : Win32 API
CAPICOM : Scriptable COM
System.Security.Cryptography.X509Certificates : .NET Framework

After a whole lot of digging I decided ( for now ) to settle on CAPICOM. I found the CAPICOM SDK and example VBScript file that shows how to load a certificate into the store. I quickly ported that over to InstallScript and bingo, it all worked.

Of course there is a catch. This has added a dependency to CAPICOM.dll to my install. This wouldn't be so horrible except the Microsoft team that created CAPICOM obviously doesn't have the first frigging clue about how Windows Installer works. They seem to think that xcopy to system32 regsvr32 is the appropriate way to deploy this ActiveX control. There are tons of references that say CAPICOM is redistributable but the only MSI available is for the entire SDK. There is no merge module or prereq package containing just the ActiveX runtime control.

So I do some googling and I find an old thread from WiX-Users with a good discussion on the component rules and why this is a problem. Finally I stumbled across a Windows Installer log file that indicates Visual Studio C# Express deploys the file to C:\ProgramFiles\CommonFiles\Microsoft Shared\CAPICOM as ComponetID {9504EA7B-206D-4178-8E37-EF70AE544903},.

Ugh, Can we say DLL HELL?!?!?

Well I suppose since the application I'm deploying targets .NET 3.5 that I could just go ahead and use the x509Store class that's in the .NET BCL but 1) I haven't tested that yet and 2) Microsoft employees keep trying to convince me that managed code custom actions are evil while at the same time they compain that other infrastructure API's don't target the CLR. ( Yes, notice even Rob Mensching joining in wishing that Windows Error Reporting supported .NET! )

Finally I found a Code Guru project using CryptoAPI writtten in C++. I tried running the sample exe but wouldn't you know it.... it was a debug EXE with a dependency on MFC42D.dll.

The cryptoAPI example is probably the purist way to go in terms of eliminating the dependency but jeesh, it shouldn't have to be this hard. What's 3 lines of script becomes pages of C++.

I once mentioned capicom in a previous post and now I know why I get so many hits for it on my statcounter.

Someone please slap me and remind me that I actually LIKE setup!


Anonymous said...

I tried right-clicking a certificate in Explorer and was hopeful when I saw an Install Certificate option. However it appears to bring up UI, so I guess that route is out...

Christopher Painter said...

Yes, that seems to invoke a (seemingly undocumented ) API in cryptext.dll called CryptExtAddCER(). It seems to be tightly coupled to it's UI as discussed in a NSIS thread. Of course those guys didn't seem to concerned about supporting silent installs. Naturally, right?

The same DLL also seems to contain some COM interfaces but those are also undocumented and tlbimp doesn't give me much to go with.

Aaron Shurts said...

I have had to deal with this in the past because of the way we handled encrypted SQL scripts.

1) Detect if it is registered on the machine, if it use, run with it
2) If not, add it to the InstallShield support files
3) Register it from the temp location, use it, and then unregister it

It sucks, but it works.