CLSIDFromProgID returns 程序 ID 错误

CLSIDFromProgID returns wrong prog id

我们有一个 .NET DLL,其中包含多个 COM classes 和合作伙伴公司可以使用的对象。我们目前使用 regasm 在注册表中注册 COM classes。这已经工作了很多年。

我们现在想摆脱 COM 注册并使用 side by side assemblies。我目前正在尝试进行此过渡,但我似乎在终点线上失败了。我们在 C++ 中提供了一个使用我们的 COM classes 的示例应用程序,我尝试在没有 COM 注册的情况下将其设置为 运行。

.NET DLL

在我们的 .NET DLL 中,我有一个 class 这样的:

namespace MyNamespace
{
    [ComVisible(true)]
    [Guid("ef828ade-b459-4446-80db-956715588601")]
    [ClassInterface(ClassInterfaceType.None)]
    [ProgId("MyVendor.MyClass")]
    public partial class MyClass
    {
    }
}

应用程序组装

应使用此 COM class 的 C++ 示例应用程序具有如下清单:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type="win32"
                        name="Microsoft.Windows.Common-Controls"
                        version="6.0.0.0"
                        processorArchitecture="x86" 
                        publicKeyToken="6595b64144ccf1df" 
                        language="*" />
    </dependentAssembly>
  </dependency>
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type="win32"
                        name="MyComDll.X"
                        version="1.0.0.0" />
    </dependentAssembly>
  </dependency>
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel level="asInvoker"
                                 uiAccess="false"></requestedExecutionLevel>
      </requestedPrivileges>
    </security>
  </trustInfo>
  <application xmlns="urn:schemas-microsoft-com:asm.v3">
    <windowsSettings>
      <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
    </windowsSettings>
  </application>
</assembly>

DLL程序集

并且 .NET DLL 本身有一个向外界公开 COM class 的清单:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <assemblyIdentity type="win32"
                    name="MyComDll.X"
                    version="1.0.0.0" />
  <file name="MyComDll.dll">
    <comClass description="MyVendor.MyClass"
              clsid="{ef828ade-b459-4446-80db-956715588601}"
              progid="MyVendor.MyClass.1"
              threadingModel="Both">
      <progid>MyVendor.MyClass</progid>
    </comClass>
  </file>
</assembly>

使用 COM

我在上面的代码示例中显然使用了代理名称,但我确保原始代码中的所有名称都有效。

在我们的示例 C++ 代码中,我们正在获取 CLSID 并以这种方式创建 class 的实例:

HRESULT hr = CLSIDFromProgID(OLESTR("MyVendor.MyClass"), &clsid);

hr = CoCreateInstance(clsid, nullptr, CLSCTX_SERVER, IID_IDispatch, (void**)(&_pMyClass));

哪里出了问题

我使用一些调试输出来检查 return 从 CLSIDFromProgID() 编辑的 GUID 并检查 return 值。如果 COM class 是使用 regasm 注册的,则 return 值为 S_OK 并且 clsid 与我在我的 .NET DLL 中指定的 GUID 相同class.

但是,如果我删除 COM 注册并使用带有清单的并排程序集,如上所示,我也会得到 S_OK return 值,但 GUID 完全不同,因此我无法创建此 class 的实例。我没有在任何地方找到从 CLSIDFromProgID() 获得的 GUID - 无论是在注册表中还是在我的开发解决方案中。

你知道我做错了什么吗?

首先,我要感谢 Joseph Willcoxson 和 Remy Lebeau 将我推向正确的方向!

我的清单中有几个小问题,我可以一个接一个地解决。我犯的一个大错误是假设我从 CLSIDFromProgID 获得的 CLSID 与我在 .NET COM class 中指定的相同。在被指出不一定如此之后,我也没有再浪费时间去检查为什么调用CoCreateInstance失败了。它翻了几次在线研究和测试来找出我犯的错误。

正如 Joseph 所指出的,我应该使用 clrClass 而不是 comClass。我在配置 clrClass 时犯了错误。例如,我对“名称”使用了与“progId”相同的名称,但 clrClass 中的“名称”是完整的名称空间 + class 名称。