如何从C ++非托管/本机DLL中免费注册的COM C#托管DLL创建COM对象

问题描述 投票:0回答:1

我正在为OBS Studio创建Heartrate Monitor插件。这个想法是在C#端访问Bluetooth GATT服务,以从Smart BT HRM中获取数据,进行渲染,然后将其传输到充当OBS Studio插件本身的C ++ dll。

我设法使所有工作正常进行,我可以从C ++端在C#中调用一个函数,该函数返回一个图像数据数组,然后可以将其提供给OBS。但是,这需要注册C#DLL。我不想用无用的DLL信息来污染注册表,所以我研究了免费注册COM。 (这也将使分发/安装lot更简单)

经过多番摆弄,我陷入了僵局。通过sxstrace,我知道并排系统正在拾取适当的库:

=================
Begin Activation Context Generation.
Input Parameter:
    Flags = 0
    ProcessorArchitecture = AMD64
    CultureFallBacks = en-US;en
    ManifestPath = C:\Program Files\obs-studio\obs-plugins\64bit\HrmPlugin.dll
    AssemblyDirectory = C:\Program Files\obs-studio\obs-plugins\64bit\
    Application Config File = 
-----------------
INFO: Parsing Manifest File C:\Program Files\obs-studio\obs-plugins\64bit\HrmPlugin.dll.
    INFO: Manifest Definition Identity is HrmPlugin,processorArchitecture="AMD64",type="win32",version="1.0.0.0".
    INFO: Reference: OBSBluetoothHeartrate,processorArchitecture="*",type="win32",version="1.0.0.0"
INFO: Resolving reference OBSBluetoothHeartrate,processorArchitecture="*",type="win32",version="1.0.0.0".
    INFO: Resolving reference for ProcessorArchitecture AMD64.
        INFO: Resolving reference for culture Neutral.
            INFO: Applying Binding Policy.
                INFO: No binding policy redirect found.
            INFO: Begin assembly probing.
                INFO: Did not find the assembly in WinSxS.
                INFO: Attempt to probe manifest at C:\Program Files\obs-studio\obs-plugins\64bit\OBSBluetoothHeartrate.DLL.
                INFO: Manifest found at C:\Program Files\obs-studio\obs-plugins\64bit\OBSBluetoothHeartrate.DLL.
            INFO: End assembly probing.
INFO: Resolving reference OBSBluetoothHeartrate.mui,language="*",processorArchitecture="AMD64",type="win32",version="1.0.0.0".
    INFO: Resolving reference for ProcessorArchitecture AMD64.
        INFO: Resolving reference for culture en-US.
            INFO: Applying Binding Policy.
                INFO: No binding policy redirect found.
            INFO: Begin assembly probing.
                INFO: Did not find the assembly in WinSxS.
                INFO: Did not find manifest for culture en-US.
            INFO: End assembly probing.
        INFO: Resolving reference for culture en.
            INFO: Applying Binding Policy.
                INFO: No binding policy redirect found.
            INFO: Begin assembly probing.
                INFO: Did not find the assembly in WinSxS.
                INFO: Did not find manifest for culture en.
            INFO: End assembly probing.
INFO: Parsing Manifest File C:\Program Files\obs-studio\obs-plugins\64bit\OBSBluetoothHeartrate.DLL.
    INFO: Manifest Definition Identity is OBSBluetoothHeartrate,processorArchitecture="AMD64",type="win32",version="1.0.0.0".
INFO: Activation Context generation succeeded.
End Activation Context Generation.

但是,当我尝试从COM对象本身创建类时,出现未找到类错误。创建它的代码如下:

static void Initialize(hrm_source *context)
{
    if (context->init_failed) return;

    try
    {
        HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
        IHrmPluginPtr pHRM(CLSID_HrmPlugin);
        context->pHRM = pHRM;
    }
    catch (_com_error _com_err)
    {
        MessageBox(NULL, _com_err.ErrorMessage(), L"Failed to initialize COM", MB_OK);
        context->pHRM = NULL;
        context->init_failed = (context->pHRM == NULL);
    }
}

问题是,如果A)我注册了程序集或B)我从exe中使用了,那么整个事情就可以了。实际上,如果我将输出类型更改为.exe,则将main()添加到plugin-dll-source并从那里创建它,我可以运行该exe,并且它可以正常工作。

                 | C++ Exe | C++ DLL 
-------------------------------------
Registered       | Works   | Works
Register Free    | Works   | Doesn't Work

显然,清单文件中缺少某些配置标志(井,手指交叉)或设置或属性缺失。

所以,这里的问题是:如何使托管的C#COM服务器和本机C ++ DLL作为COM客户端使用免费注册的COM?

这里还有清单文件:

COM服务器(C#DLL)

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <assemblyIdentity type="win32"
                    name="OBSBluetoothHeartrate" 
                    version="1.0.0.0" 
                    processorArchitecture="amd64"/>
  <clrClass clsid="{54667DC4-13CD-4D25-BB9E-C3BDDFAF019F}" 
            progid="OBSBluetoothHeartrate.HrmPlugin" 
            threadingModel="Both" 
            name="OBSBluetoothHeartrate.HrmPlugin" 
            runtimeVersion="v4.0.30319"/>
</assembly>

COM客户端(C ++ DLL)

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <assemblyIdentity type="win32"
                    name="HrmPlugin"
                    version="1.0.0.0"
                    processorArchitecture="amd64"/>
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type="win32"
                        name="OBSBluetoothHeartrate"
                        version="1.0.0.0"
                        processorArchitecture="amd64"/>
    </dependentAssembly>
  </dependency>
</assembly>

2020年1月17日更新

我也向C ++ DLL添加了assemblyIdentity,以防它有所帮助(根据注释中的问题)。唯一更改的是,现在当它由并行系统加载时,它将获得一个身份而不是(null)-不需要身份,因为我没有将C ++ DLL用作COM服务器。但是,我已经更新了C ++ DLL清单和sxstrace日志-从技术上来说,这现在“更正确”,因此至少我们知道这不是原因。

2020年1月29日更新

我不小心将C#DLL COM服务器清单复制为C ++ DLL COM客户端清单。现在已更新为正确的版本。确保仔细检查它,但是即使sxstrace说找到并加载了正确的dll,也仍然找不到该类。我将尝试作为答案提供的手动激活上下文创建并进行报告(当然,如果可以使用它,则将其标记为正确的答案)

c# c++ .net dll com
1个回答
0
投票

这里是使用手动激活上下文的答案的骨架...函数ReportError()是一个存根...用它来做您想做的...日志,跟踪,消息框或将其删除...] >

   ACTCTX ctx = { sizeof(ctx),  ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID, _T("NameOfYourDotNet.manifest")};
   ctx.lpAssemblyDirectory = szPath; // path is drive and directory where your COM DLL is


   HANDLE hCtx = CreateActCtx(&ctx);
   if (hCtx != INVALID_HANDLE_VALUE)
   {
      DWORD_PTR dwCookie = 0;
      BOOL bActivated = ActivateActCtx(hCtx, &dwCookie);
      if (bActivated)
      {
         wcout << L"After activating ActCtx..." << endl;


     // Do stuff with your .NET COM server here

         DeactivateActCtx(0, dwCookie);
      }
      else
      {
         ReportError(L"Could not activate context: ", GetLastError());
      }
      ReleaseActCtx(hCtx);
   }
   else
   {
      ReportError(_T("Problem creating ActCtx: "), GetLastError());

   }
© www.soinside.com 2019 - 2024. All rights reserved.