如何在点网中使用免注册COM dll

Hem*_*yal 5 c# c++ com activex regfreecom

在我的一个项目中,我有一个使用C++ DLL的c#应用程序.目前在客户端PC上,我们在注册表中的COM组件上注册C++ DLLS,以便我们在C#中使用它们.

我在NET上了解到有一个免费解决方案可以从微软获得链接http://msdn.microsoft.com/en-us/library/ms973913.aspx

但阅读后我没有太多线索,因为我的应用程序架构如下所示

  1. 我有2个C++ dll LET SAY CPForms.dll和Rules.dll.
  2. Rule.dll包含在CPForms.dll中
  3. 我有1个C#dll让我说使用CPForms.DLL的ConsumeForm.dll
  4. 我有另一个使用ConsumeForm.dll的C#Exe

我的客户端只打开C#Exe,后者又调用ConsumeForm.dll,它进一步调用CPForms.dll,显示C++表单(UI),有按钮验证,当用户在内部使用C++ Rules.dll单击该按钮时.目前我在注册表中注册了两个C++ dll.

现在客户端只希望将Rule.dll作为RegFree安装引用,因为Rule.dll经常更改,并且客户端不想使用管理员帐户一次又一次地注销和注册.

其他那个客户端可以注册CPForms.dll.

我的问题是我们如何生成清单文件?它在我的场景中将如何运作?

Ben*_*Ben 9

注意:请考虑在此处使用清单,以获得更好的解决方案:

怎么做没有清单

在COM注册表是一个服务可选的一个进程内的服务器.

再次:您不必注册对象以创建它. 如果它没有注册,(而不是在清单中)则无法创建它CoCreateInstance,因为注册表(或清单)是告诉CoCreateInstance加载哪个DLL的.

但是你可以创建LoadLibrary,GetProcAddress,DllGetClassObjectIClassFactory::CreateInstance.

(注意,您不会获得任何COM +服务,也不能以这种方式创建进程外对象,或者线程模型与创建线程不兼容的对象.如果您不要求COM为您执行此操作这些事情成了你的问题).

CoCreateInstance提供的服务是为LoadLibrary的调用找到正确的DLL,并为您调用其他函数.(并且检查线程模型是兼容的,在相应的线程上创建,并使用CoMarshalInterthreadInterfaceInStream/CoUnmarshalInterfaceAndReleaseStream来编组接口,如果它们不是.这听起来像很多工作但是如果你只有一个STA therad你几乎可以忽略所有问题.)

像这样的东西应该做的伎俩:

// 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;
}
Run Code Online (Sandbox Code Playgroud)

注意:这将允许您创建对象.但是,如果您调用的对象本身依赖于已注册,则它将无法正常运行.

特别是,许多IDispatch实现依赖于类型库.如果是特定对象的情况GetIDsOfNames,GetTypeInfo则会失败,并且您将无法对该对象使用后期绑定方法.这包括dynamic在C#中使用,以及使用Python等动态语言.

其他方法,如双接口方法和不从IDispatch继承的接口可能会工作,但即使IDispatch方法不这样做.

底线:为了使免注册COM工作,被实例化的对象不得依赖于自己的注册.