views:

337

answers:

2

Scenario: I have a project containgin two C# projects, which for historical reasons must communicate with each other using COM (via COM Interop). The COM Server is an in-process automation object (call this the "Server") and the COM Client is a simple C# Console application that loads the server like this:

        var objTypee = Type.GetTypeFromProgID("ProgID.Interop3264");
        var objLateBound = Activator.CreateInstance(objType);

Visual studio automatically registers assemblies for COM Interop if that option is enabled in the project settings, so that's what I use to register the Server (I'm only interested in the developer experience here, installation is a seperate issue) and everything works fine as long as the projects are set to generate 32-bit code or the COM Client is 32-bit.

The problem comes when developing on a 64-bit system and both projects are set to generate code for 'Any CPU' which results in them running in 64-bit mode. This yields the following error:

"Retrieving the COM class factory for component with CLSID {6F597EDF-9CC8-4D81-B42E-1EA9B983AB02} failed due to the following error: 80040154."

After some investigation, it seems that the MSBuild scripts only perform 32-bit registration. It does put the ProgID into the 64-bit registry section, along with its subkey CLSID, and the proper classID. But the CLSID{clsid} stuff is not there. It's only in the WOW6432 subtree, for 32-bit. So the activator cannot retrieve the class factory because it can't find the thing.

I'll be really impressed with the SO community if I get an answer to this one, but here goes:

Has anyone else run accross this problem? How did you solve it? What's the easiest way to ensure that COM Interop assemblies get correctly registered on 64-bit development machines?

+2  A: 

We've encountered this problem and solved it by setting projects up to generate assemblies for x86. This is suboptimal, of course, but we also have several native 32-bit libs, so we had to do that anyway.

elder_george
That's one solution, but I had hoped to keep everything native 64-bit if possible. With 64-bit systems rapidly becoming the norm, I'd rather not have to develop in 32-bit then get nasty surprises when I finally install onto a 64-bit system.
Tim Long
A: 

I was able to solve this with the following KB item. Basically I turned off registering for COM interop in the project build settings, and used the post-build command:

"%Windir%\Microsoft.NET\Framework64\v2.0.50727\regasm" "$(TargetPath)" 

http://support.microsoft.com/kb/956933

Jeremy Mullin
Thanks Jeremy, that is certainly one solution. The problem is that we are a team of developers working on a mixture of 32-bit and 64-bit systems. Hard-coding a path to the 64-bit RegAsm will obviously not work on a 32-bit system. I had hoped to use "Any CPU" and just have visual studio figure out what to do. So now we set our debug builds to x86. Out build server targets Any CPU for the release build and luckily it is a 32-bit server so there are no registration issues there.
Tim Long
Doesn't the use of %windir% environment variable solve this? On 64-bit system this will be the 64-bit regasm. On 32-bit it will be the 32-bit regasm, right? -- Nevermind, I just scoped the "Framework64" in the path...
Jeremy Mullin

related questions