Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use Registration free COM dll in dot net

In one of my Project, I have c# application which is using C++ DLL. Currently at client PC we are registering C++ DLLS at COM components in the registry so that we will use them in C#.

I learn on NET that there is a Reg Free solution available from microsoft at link http://msdn.microsoft.com/en-us/library/ms973913.aspx

But after reading I didn't get much clue because my application architecture is different as following

  1. I am having 2 C++ dlls LET SAY CPForms.dll and Rules.dll.
  2. Rule.dll is include inside CPForms.dll
  3. I have 1 C# dll let say ConsumeForm.dll which is using CPForms.DLL
  4. I have another C# Exe which is using ConsumeForm.dll

My client is only opening C# Exe which in turn is calling ConsumeForm.dll which is further calling CPForms.dll which shows C++ form (UI), there is button validate, when user click that button it internally using C++ Rules.dll. Currently I am registering both C++ dlls in registry.

Now client only want Rule.dll to be referenced as RegFree installation, because Rule.dll changes frequently and the client don't want to unregister and register again and again using Admin account.

Other then that client is OK with registration of CPForms.dll.

My question is how we can generate manifest file? And how it will work in my scenario?

like image 895
Hemant Kothiyal Avatar asked Feb 09 '12 11:02

Hemant Kothiyal


People also ask

What is register free COM?

Registration-free COM interop activates a component without using the Windows registry to store assembly information. Instead of registering a component on a computer during deployment, you create Win32-style manifest files at design time that contain information about binding and activation.


2 Answers

Note: Consider using a manifest as in the answer here for a better solution:

  • How to use AutoItX in .NET (C#) without registering

How to do it without a manifest

The COM registry is a service which is optional for an inproc server.

Again: You do not have to register an object in order to create it. If it is not registered, (and not in a manifest) you cannot create it with CoCreateInstance, because the registry (or manifest) is what tells CoCreateInstance which DLL to load.

However you can create it with LoadLibrary, GetProcAddress, DllGetClassObject and IClassFactory::CreateInstance.

(Note you will not get any COM+ services, and you cannot create out-of-process objects in this way, or objects whose threading model isn't compatible with the creating thread. If you don't ask COM to do it for you these things become your problem).

The service which CoCreateInstance provides is to locate the correct DLL for the call to LoadLibrary, and just call the other functions for you. (And checking the threading models are compatible, creating on the appropriate thread, and using CoMarshalInterthreadInterfaceInStream/CoUnmarshalInterfaceAndReleaseStream to marshal the interface if they are not. That sounds like a lot of work but if you just have one STA therad you can pretty much ignore all the issues.)

Something like this should do the trick:

// Really you should break this up int GetClassFactoryFromDLL, then reuse the class factory.
// But this is all from memory...
// Load CLSID_MyID, from DLL pszMyDllPath
typedef HRESULT __stdcall (*_PFNDLLGETCLASSOBJECT)(
  __in   REFCLSID rclsid,
  __in   REFIID riid,
  __out  LPVOID *ppv
) PFNDLLGETCLASSOBJECT;

HRESULT CreateInstanceFromDll(LPCTSTR pszMyDllPath, CLSID clsidMyClass, IUknown** ppunkRet)
{
    // Handle bad callers
    *ppunkRet = NULL;
    HANDLE hDLL = LoadLibrary(pszMyDllPath);
    if(hDLL == NULL)
    {
        // Failed to load
        return HRESULT_FROM_NTSTATUS(GetLastError());
    }
    PFNDLLGETCLASSOBJECT pfnDllGetClassObject = GetProcAddress(hDLL);
    if(pfnDllGetClassObject == NULL)
    {
        // Not a COM dll
        HRESULT hrRet = HRESULT_FROM_NTSTATUS(GetLastError());
        FreeLibrary(hDLL);hDLL = NULL;
        return hrRet;
    }
    IClassFactory* pClassFactory = NULL;
    HRESULT hr = pfnDllGetClassObject(clsidMyClass, IID_IClassFactory, &pClassFactory);
    if(FAILED(hr)){
        FreeLibrary(hDLL);hDLL = NULL;
        return hr;
    }
    hr = pClassFactory->CreateInstance(NULL, IID_IUnknown, &ppunkRet);
    pClassFactory->Release();
    if(FAILED(hr))
    {
        *ppunkRet = NULL;
        FreeLibrary(hDLL);
        return hr;
    }
    return hr;
}

Note: This will allow you to create the object. However if the object you call is itself reliant onbeing registered, it will not function correctly.

In particular, many IDispatch implementations rely on the type library. If that's the case for a particular object, then GetIDsOfNames and GetTypeInfo will fail, and you will not be able to use late-bound methods with the object. This includes using dynamic in C#, and dynamic languages such as Python.

Other methods such as dual interface methods and interfaces not inheriting from IDispatch may well work however even if the IDispatch methods do not.

Bottom line: For registration-free COM to work, the object being instantiated must not rely on its own registration.

like image 154
Ben Avatar answered Sep 20 '22 11:09

Ben


For those who will jump to this question in search for Registration free COM dll in dot net, I was able to use AutoItX COM object in Reg Free manner from C# in this answer https://stackoverflow.com/a/19996424/173073. Creating and using other Reg Free objects would be similar.

like image 25
Dzmitry Lahoda Avatar answered Sep 18 '22 11:09

Dzmitry Lahoda