How to invoke 64bit native COM from 32bit .Net application

Recently, we got an issue from customer. They have a 32bit .Net application and use AdminIndexServer object to manage Indexing Service. Bellow error reported when running this application on 64bit Windows as there is no 32bit Indexing Service Admin Object on 64bit Windows.

Retrieving the COM class factory for component with CLSID {3BC4F3A1-652A-11D1-B4D4-00C04FC2DB8D} failed due to the following error: 80040154.

What customer does is using tlbimp.exe to generate a managed wrapper assembly for AdminIndexServer object and reference this wrapper assembly in their .Net application.

Here is the easiest solution I can image:

- Create a managed wrapper assembly with “/machine:Agnostic” option.

- Reference this assembly in .Net application.

- Compile .Net application to “Any CPU”

Now, we will have an “Any CPU” .Net application. It is a 32bit application when run on X86 systems, and became a 64bit application when run on 64bit system.

However, this is not feasible for customer as their application can only be run in 32bit mode due to a lot of dependencies. We need a solution to invoke 64bit native COM from 32bit application.

We finally found a solution using System.Activator. Here are the details steps:

- Create a new COM+ application and add AdminIndexServer(ciodm.dll) to this COM+ application. Then, whenever we create an instance of AdminIndexServer, it will be created in 64bit dllhost.exe rather than the original in-proc mode. Here is the steps:

o Click “start” -> “run” -> type and run “dcomcnfg”

o Expand “Component Services” and locate to “Com+ Applications”

o Right click and select “new” -> “application”

o “Next” -> “Create an empty application”

o Type the application name like “Indexing Component”, Select “Server application” and click “Next”

o Select the account to this application, like “Interactive user”. This can be changed any time after setup. Click “Next”

o Click “Next”, “Finish”

o Locate to the COM+ application just created, and select “Components”

o Right click and select “New” -> “Component”

o Select “Install New Component”

o Browse to system32\ciodm.dll

o Next and finish

- Using System.Activator to invoke the COM method directly without any reference. This is something like we can CoCreateInstance in C++.

                Type comType;

                object comObject, catObj;

                //Create the ISADM object

                comType = Type.GetTypeFromCLSID(new Guid("3BC4F3A1-652A-11D1-B4D4-00C04FC2DB8D"));

                //GetTypeFromProgID("Microsoft.ISAdm"); //This doesn’t work

                comObject = Activator.CreateInstance(comType);

                //This is the parameter for GetCatlogByName;

                object[] par = new object[1];

                par[0] = new object();

                par[0] = "Test";

                //Call GetCatalogByName to get the catObj

                catObj = comType.InvokeMember("GetCatalogByName", BindingFlags.InvokeMethod, null, comObject, par);

                        //Get IsupToDate property from CatAdm

                object result = catObj.GetType().InvokeMember("IsupToDate", BindingFlags.GetField | BindingFlags.GetProperty, null, catObj, new object[] { });

                Console.WriteLine("IsuptoDate : {0}", result.ToString());

                //call IsCatalogRunning of CatAdm

                result = catObj.GetType().InvokeMember("IsCatalogRunning", BindingFlags.InvokeMethod, null, catObj, new object[] { });

                Console.WriteLine("IsCatalogRunning : {0}", result.ToString());

Best Regards,

Zhao Wei