Showing posts with label com-interop. Show all posts
Showing posts with label com-interop. Show all posts

What to do when CryptAcquireContext() fails

I’m using CryptoAPI to do encryption and encountering an error on Win2008 Terminal Server which enforces Mandatory Profiles. CryptAcquireContext() fails with a message of either “keyset not found” or “The profile for the user is a temporary profile”.

I’ve tried the same test on WinXP using a guest account and got the same thing.

So, what gives?

Well, this blog post (RSACryptoServiceProvider fails when used with mandatory profiles) way back in 2007 by @alejacma explains:

CryptAcquireContext will fail with NTE_TEMPORARY_PROFILE error when called from a mandatory profile.

Mandatory profiles are read-only user profiles. Since changes to the mandatory profile cannot be saved, PKI design doesn't allow this operation, and CryptAcquireContext prevents this scenario by failing.

The moral of this story is: RSA sucks, and I am now Rijndael’s new biggest fan.

By the way, troubleshooting this problem had given me the chance to learn a few more WinDbg commands:

.sympath srv*http://msdl.microsoft.com/downloads/symbols
.sympath+ c:\localsymbols
.reload –f
bm /a advapi32!CryptAcquireContext*

COMException : Creating an instance of the COM component with CLSID {…}

I recently changed my NAnt build script, as part of its post-build cleanup step,  to unregister all .NET COM interop components after doing the build. Now my unit tests fails with this error:

System.Runtime.InteropServices.COMException : Creating an instance of the COM component with CLSID {596C3AA2-D5EC-4F86-85E3-7FAF86EC17A3} from the IClassFactory failed due to the following error: 800a005b.

What’s the cause?

Here are the facts: My .NET lib X depends on a  COM lib Y (596C3AA2-D5EC-4F86-85E3-7FAF86EC17A3), which depends on COM lib Z, which in turn invokes  .NET COM interop lib N.

It turns out that the real culprit was N, which wasn’t registered for some reason, even though I’ve told it to register via the regasm NAnt task.

Well, as it turned out, I needed to add the codebase=”true” attribute to the regasm task that registers N, which makes sense in hindsight, because my DLLs are not all in the same directory. Another “doh!” I suppose.

stdole 7.0.3300.0

When I first got this error during the initialization phase of my component:

Could not load file or assembly 'stdole, Version=7.0.3300.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system cannot find the file specified.

I thought that it wanted Interop.stdole.dll, which was sitting right there in the working directory. But as it turned out, it meant the Primary Interop Assembly called stdole.dll, which was indeed missing.  Duh!

Unable to cast COM object of type ‘X’ to interface type ‘_X’

I added a new property to my COM class and consequently bumped up its minor version by 1, did some testing with it, and then decided that I wanted to run a clean build.  Now my existing NUnit test cases that use this class are failing with the following message:

Unable to cast COM object of type MyLib.MyClass' to interface type MyLib._MyClass'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{…}' failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)).,

The interesting thing is that everything compiled without a hitch.  Is this  .NET’s version of BadImplementsRefInCompatLib?

Looking that the COM library’s IDL info via oleview.exe , it turned out that the interop assembly was bound to version 1.3 of the COM library, whereas 1.2 was registered on my machine. I regenerated the COM interop assembly for 1.2, and the problem went away.

Why it's good to use [System] Hungarian notation

One of our components has a property called--for reason of obscurity say--URL. The code behind it is quite simple:


public string URL {
get {
return mstrURL;
}
set {
mstrURL = value;
}
}



This property is being edited through our Property Editor component via a sort of reflection mechanism.

Sometime ago, this component broke because the Property Editor was no longer able to "reflect" on the URL property.

A bit of googling turned up this MSKB article: "Type library identifiers are not case sensitive by design".

It turned out that somebody recently added this method in a completely different class, within the same assembly, but entirely unrelated to the component above:

public void LoadUrl(string url) {
...
}



So the code that gets called by RegAsm to generate the type library must have found the url parameter of the LoadUrl method first, and decided to reuse it as the moniker for our URL property.

I guess the moral of this story is: Stick with System Hungarian Notation.

public void LoadUrl(string strUrl) {
...
}


(Side Note: A good article on Hungarian Notation can be found at Joel On Software).