Follow GFI:
Find us on Facebook Follow us on Twitter Find us on Linkedin Subscribe to our RSS Feed Find us on YouTube Find us on Google+
 

Using a 32bit COM object in a 64bit environment

on September 14, 2009

A while ago I ran into a problem while working on a 64bit application. I needed to use a 32bit COM object in my 64bit application but alas that didn’t work.

It seems that by default 32bit COM objects are not usable in a 64bit environment. Trying to access a 32bit COM in a 64bit environment will result in a class not registered error. However this can be countered using dllhost as a surrogate for the 32bit COM object.

To do this, it involves a small number of simple registry hacks:

  • Locate your COM object GUID under the HKey_Classes_Root\Wow6432Node\CLSID\[GUID]
  • Once located add a new REG_SZ (string) Value. Name should be AppID and data should be the same COM object GUID you have just searched for
  • Add a new key under HKey_Classes_Root\Wow6432Node\AppID\
    The new key should be called the same as the com object GUID
  • Under the new key you just added, add a new REG_SZ (string) Value, and call it DllSurrogate. Leave the value empty
  • Create a new Key under HKey_Local_Machine\Software\Classes\AppID\
    Again the new key should be called the same as the COM object’s GUID. No values are necessary to be added under this key.

That’s it, your COM Object should now be accessible from a 64bit environment and can be used like a regular COM Object.

Hope this helped you out. If you have any questions feel free to leave a comment and I will try to help if possible.

 
Comments
Richard September 14, 20092:43 pm

Nice work around.

Imran September 24, 20096:04 pm

Yes, I agree Excellent workaround. Has saved my day actually night.

Thanks,

Emmanuel Carabott September 25, 20098:51 am

You’re welcome people, glad to have helped :)

Kevin December 1, 20097:14 pm

Actually, many of the COM problems that people think originate from the bit-depth of the system it was compiled on, turn out to actually be due to the way the COM object was registered.

COM object types are registered via registry keys. This is what the regasm.exe utility does (writes to the registry). 32-bit bit registry nodes and distinctly different than 64-bit registry nodes.

That is why the .NET framework comes with 2 versions of regasm.exe. One version in the “Framework” path, and the other in “Framework64″ path.

Basically it comes down to the bit-depth of the consuming application. For example, Excel 2007 actually is a 32-bit application. Any COM component it consumes MUST be registered with the 32-bit version of regasm.exe, because the Excel process will be looking in the 32-bit compatible registry nodes.

At my company, we have used both the same COM component compiled on 32-bit machine or on 64-bit machine, and BOTH work in 32-bit Excel as long as the COM objects are registered with 32-bit regasm.exe. If either COM object is registered with the 64-bit regasm.exe, then neither of the COM objects will work (because Excel is checking the 32-bit registry values and not finding the desired COM object there).

My guess is that the dllhost workaround above is just a clever, but circuitous way to solve this simple underlying issue.

Ebbe Høeg Jensen February 24, 20102:45 pm

Hello and thanks.

When you reach this point:

■Create a new Key under HKey_Local_Machine\Software\Classes\AppID\
Again the new key should be called the same as the COM object’s GUID. No values are necessary to be added under this key.

… the new key allready exists, and it holds a ‘dllsurrogate’ value. What could this mean? I still cant contact my 32-bit after adding your registry modifications.

It looks as if my DLL holds three GUIDs. I have only implemented one of them. But I believe its the main GUID.

Best regards, Ebbe

Ebbe Høeg Jensen February 25, 201012:52 pm

Hi again. Sorry. Your solution works. Thanks. Best regards, Ebbe

Raien March 9, 20107:55 am

Hi,

I’ve tried the hack and it works fine but now we switched to Windows Server 2008 R2 and when I want to create the key ‘HKEY_LOCAL_MACHINE\SOFTWARE\CLASSES\APPID\{GUID}’, this key already exists with the ‘DLLSurrogate’ value.

It seems that Windows Server 2008 R2 doesn’t have dedicated registry keys for WOW6432 –> http://msdn.microsoft.com/en-us/library/aa384235(VS.85).aspx

Has anybody a workaround/solution for me?

Best regards
Raien

Simon March 15, 20103:51 am

Emmanuel:
Does this apply to typelib registered COM object. I am not a low level programmer. The COM GUID is in the Wow6432Node\TypeLib.

The interfaces are in interfaces. Should the steps be the same.

Kevin:
If I use the 32bit version of regasm then I accomplish the same thing, correct?

Thank you both in advance.

Eli March 17, 20106:57 pm

Emmanuel, you have no idea how much you’ve helped. 3 programmers have spent more than a week trying to figure out how to solve this and your solution did the trick in just 2 minutes work.

Thanks alot :)

Eli.

Emmanuel Carabott March 23, 201011:58 am

Hi Raien,

Sorry to hear about your issue, I am afraid I wasn’t in that situation and do not know of a workaround. I did a quick search however and came across this post on MSDN: http://blogs.msdn.com/volkerw/archive/2009/02/09/32-bit-optional-in-windows-server-2008-r2.aspx

It might be worth a try. If it works for you please let me know; I would appreciate that :) Thanks!

Emmanuel Carabott March 23, 201012:23 pm

Hi Simon,

Honestly I don’t know, I suspect it might not work however. Did you try it by any chance? if so what was the result?

Emmanuel Carabott March 23, 201012:25 pm

Hi Ebbe and Eli,

Glad this workaround helped you out!

Ian March 24, 20109:37 pm

Kevin, if your COM interfaces are loaded out of process, then it doesn’t matter the bitness of the housing exe or DLL. This could be why Excel doesn’t care about the bitness, but as your server is 32bit you will always need to register it in the 32bit portion of the registry.

Siraj Zarook June 7, 201011:32 am

Hi Simon

Yes it works for typelib registered COM objects as well. A very good piece of work. You certainly saved lot of hassle.

regards,

Siraj Z

siraj June 9, 20105:38 pm

Thanks it worked for me.

regards,

Ken July 15, 201012:19 am

Hi Raien,

Yes the keys were there in Windows 2008 R2. But the string entry “DllSurrogate” in key under HKey_Classes_Root\Wow6432Node\AppID\[AppID]\ was not there. I added the string “DllSurrogate” in and then 32-bit COM DLL works in 64-bit Windows 2008 R2.

Thanks to Emmanuel for saving me days of work.

Regards,

Emmanuel Carabott July 21, 20104:56 pm

glad to help :)

RUPS August 10, 201012:38 pm

What a wonderful piece of sharing ! It worked for me. Thanks a ton !! It saved my life :)

Carlos August 19, 20109:30 pm

Hi Emmanuel,

Yesterday I have spent several hours learning how to configure IIS 7.5 in order to use 32 bits worker processes, since I have to publish an ASP (VBScript) Website in Windows Server 2008 R2. That website is now running in a Windoews 2000 server and uses old COM objects.

Do you think that if I apply your hacks for the COM objects that I need, then the ASP pages will run in the new server without any additional 32 bits configuration?

Thank you in advance for your support.

Carlos

Carlos August 19, 20109:46 pm

It would be great since W2008 can’t manage simultaneous 32 and 64 bits procceses in the same application pool.

Another advantage is that except for the COM objects, the Web server remains enabled only fot 64 bits applications.

Alex October 27, 20109:14 am

Encountered problem with COM inter-op calling after installing and setting up our 32bit .NET DLL library in Windows 2008 R2 64bit server.

It’s working now. Thanks!!!

Danny October 28, 201011:57 pm

Hi, on 64bit systems prior to windows server 2008 R2 and Win7, be sure to put everything under Wow6432node. The first time I tried this I had my com launching the 64-bit DllHost, which didn’t help as I needed 32-bit host.

I registered my com with c:\windows\syswow64\regedit and then placed the keys described above under their corresponding Wow6432Node locations.

Thanks so much for this solution!!

Alex November 10, 201011:37 am

Hi Emmanuel,

Thanks for the post. Now i can create object and call subs with simple arguments (strings, numbers) but i cannot send complex objects (reference to other com classes). Error: Invalid procedure call or argument. Do you have some idea?

Thanks

Emmanuel Carabott November 10, 20102:00 pm

Hi Alex,

Sorry to hear that you’re encountering this difficulty. Since I didn’t run into it personally, I cannot comment offhand; however, feel free to post code examples of what you’re trying to do and maybe I can help then.

I can’t see why it shouldn’t work, unless the com objects you’re referring to are 64 bit themselves really.

SD December 1, 201011:27 pm

Hi Emmanuel,

Thanks for the post.

I have made all the registry changes you suggested, but still cann’t access 32-bit COM dll. I am using Windows XP Professional x64.

Any help is appreciated.

Thanks

Emmanuel Carabott December 2, 201012:59 pm

Hi SD, should work just fine under Windows XP x64. Can you give me a bit more information of what’s happening to you? What error you’re receiving perhaps? And what com object you’re trying to use?

I would also suggest that you try to access it in 32 bit to ensure the com is registered correctly.

SD December 2, 20106:15 pm

Hi Emmanuel,

This 32bit COM is installed on the client machine via CAB file. I can access this COM from IE-8 32bit. But doesn’t work from IE-8 64 bit. It gives “Object doesn’t support this property or method” error.

If I try to access this 32bit COM from .NET windows app[x86], it works fine. But when I try to access it from .NET windows app[x64], I get this error: “Retrieving the COM class factory for component with CLSID failed due to error 80040154″.

Please help.

Aaron May 17, 201111:30 pm

This is not *quite* working for me. CoCreateInstance returns a pointer and S_OK, I can see dllhost launched and running with my GUID, but QueryInterface returns E_NOINTERFACE.

Rachel July 1, 201110:50 pm

Hi,

I made the registry changes, but I now receive the following error:

Retrieving the COM class factory for component with CLSID [class guid] failed due to the following error: 80070005.

Anything I missed?

Thanks,
Rachel

Tobias August 11, 20112:10 pm

Hello,

I tried this for my COM DLL but it does not work for DLL surrogation. According to this article (http://msdn.microsoft.com/en-us/library/aa384235%28v=VS.85%29.aspx) all registry keys which includes InProcServer32-IDs are not reflected because Microsoft assumes that these are only InProc-Calls and not Out-Of-Proc-Calls. A CoCreateInstance-Call would return “CLASS_NOT_REGISTERED” because it does not find the key in the 64-bit section.

Has anybody an idea how to get reflected the key with using of DLL surrogation?

Emmanuel Carabott August 11, 20114:46 pm

Hi Tobias,

I didn’t run into your problem so this might not work, but none the less worth a shot I guess. Did you try setting the CLSCTX_LOCAL_SERVER flag for dwClsContext in the CoCreateInstance Call?

This should theoretically force the com to use the localservice key which according to your link is reflected. Might work, definitely worth a shot.

 
Tobias August 12, 201111:19 am

Hello Emmanuel,

thanks for your quick reply. I used as flag “CLSCTX_LOCAL_SERVER” and “CLSCTX_ACTIVATE_32_BIT_SERVER” and also tried only one of them but nothing changed.
“CoCreateInstance” will return “CLASS_NOT_REGISTERED”. In this article (http://msdn.microsoft.com/en-us/library/aa384253%28v=VS.85%29.aspx) they specified why reflection would be disabled.

Have you run 32-bit-surrogation in this way with Windows 7?

Regards,

Tobias

 
Sandeep September 13, 20118:14 am

Dear emmanuel, i am using windows 7.I created COM dll in win32 and followed process suggested by you ,but it is not working for me.Let me know your mail ID if possible then will send you code to analyze.
i am calling COM as

IClassFactory *pclsf;
IUnknown *pUnk;
IStepfile *pstep;
int x,y;
long result;
CoInitialize(NULL);
HRESULT hr= CoGetClassObject(STEPFILE_CLSID,CLSCTX_INPROC,NULL,IID_IClassFactory,(void**)&pclsf);
hr = pclsf->CreateInstance(NULL,IID_IUnknown,(void**)&pUnk);
hr=pUnk->QueryInterface(IID_IStepfile,(void**)&pstep);
result = pstep->AddNum(1,2);

 
Emmanuel Carabott September 13, 201112:56 pm

I am sorry to hear you’re having trouble with this. Seems like a lot of people are having trouble with this work around on Windows 7.

Most probably Microsoft changed something in Windows 7 that disabled this workaround. What error are you experiencing? Is it the same as Tobias was experiencing above? And, did you try the same process I suggested to him?

Christian Fries April 9, 20129:58 am

Windows 7 changed the way 32 bit keys are reflected in the registry. I left this in a longer comment here , but some how the comment was deleted. Maybe it was considered spam (was linking to my page). I have some details in my blog (which also links back to this page).

However, you can make this work under Win 7, but it should be noted, that this workaround is sometimes not needed. The problems with 32bit / 64bit registry stuff is often that you use a 32 bit application to register a 64 bit assembly – this does not work since 32 bit applications do not see 64 bit registry by default.

 
Mathi October 27, 20112:29 pm

Hi Emmanuel,

The registry hack solution is not working for me. I’m getting the following error

“Unable to cast COM object of type ‘NewAtlProjectLib.InmAtlsimpleobject1Class’ to interface type ‘NewAtlProjectLib.IInmAtlsimpleobject1′. This operation failed because the QueryInterface call on the COM component for the interface with IID ‘{0D5A58FA-5C0E-4AC1-9064-9C5A2C51FD55}’ failed due to the following error: Class not registered (Exception from HRESULT: 0×80040154 (REGDB_E_CLASSNOTREG)).”

My environment details are
Building com objects –> C++ 32 bit DLL
Wrapper DLL –> C# 64bit dll
Client application –> C# 64 bit windows application
Build environment –>W2K8 SP2 + VS2008

The client application function is
public int samplefunction(int val)
{
InmAtlsimpleobject1Class c1 = new InmAtlsimpleobject1Class(); //here succeeds
int val1 = c1.DoSomething(); //here failed with above error
return val;
}

Please suggest. Any other change is registry entry required ?

Thanks
Mathi

Kyle December 28, 20115:08 pm

Has anyone for whom this hack hasn’t worked found out an alternate solution?

I’m trying to use CoCreateInstance on a Visual SourceSafe DLL.