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 - 无论是在注册表中还是在我的开发解决方案中。
你知道我做错了什么吗?
- 我知道我的 C++ 示例应用程序通常与我们的 COM 对象一起工作得很好,因为如果 COM classes 已注册,它就可以完美地工作。
- 我检查了我使用 Microsoft's specification 和各种指南创建的清单的每个部分。
- 我在 Windows 事件日志中没有收到任何 SideBySide 错误,所以我知道清单格式正确。
- 我确实从
CLSIDFromProgID()
得到了一个 S_OK
,所以我知道找到了 ProgID - 它只是提供了错误的 CLSID。
- 我使用函数
StringFromCLSID()
来比较由 `CLSIDFromProgID() 找到的 CLSID。
首先,我要感谢 Joseph Willcoxson 和 Remy Lebeau 将我推向正确的方向!
我的清单中有几个小问题,我可以一个接一个地解决。我犯的一个大错误是假设我从 CLSIDFromProgID 获得的 CLSID 与我在 .NET COM class 中指定的相同。在被指出不一定如此之后,我也没有再浪费时间去检查为什么调用CoCreateInstance失败了。它翻了几次在线研究和测试来找出我犯的错误。
正如 Joseph 所指出的,我应该使用 clrClass 而不是 comClass。我在配置 clrClass 时犯了错误。例如,我对“名称”使用了与“progId”相同的名称,但 clrClass 中的“名称”是完整的名称空间 + class 名称。
我们有一个 .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 - 无论是在注册表中还是在我的开发解决方案中。
你知道我做错了什么吗?
- 我知道我的 C++ 示例应用程序通常与我们的 COM 对象一起工作得很好,因为如果 COM classes 已注册,它就可以完美地工作。
- 我检查了我使用 Microsoft's specification 和各种指南创建的清单的每个部分。
- 我在 Windows 事件日志中没有收到任何 SideBySide 错误,所以我知道清单格式正确。
- 我确实从
CLSIDFromProgID()
得到了一个S_OK
,所以我知道找到了 ProgID - 它只是提供了错误的 CLSID。 - 我使用函数
StringFromCLSID()
来比较由 `CLSIDFromProgID() 找到的 CLSID。
首先,我要感谢 Joseph Willcoxson 和 Remy Lebeau 将我推向正确的方向!
我的清单中有几个小问题,我可以一个接一个地解决。我犯的一个大错误是假设我从 CLSIDFromProgID 获得的 CLSID 与我在 .NET COM class 中指定的相同。在被指出不一定如此之后,我也没有再浪费时间去检查为什么调用CoCreateInstance失败了。它翻了几次在线研究和测试来找出我犯的错误。
正如 Joseph 所指出的,我应该使用 clrClass 而不是 comClass。我在配置 clrClass 时犯了错误。例如,我对“名称”使用了与“progId”相同的名称,但 clrClass 中的“名称”是完整的名称空间 + class 名称。