CLSIDFromProgID 返回错误的 prog id
Posted
技术标签:
【中文标题】CLSIDFromProgID 返回错误的 prog id【英文标题】:CLSIDFromProgID returns wrong prog id 【发布时间】:2021-10-25 22:38:27 【问题描述】:我们有一个 .NET DLL,其中包含合作伙伴公司可以使用的多个 COM 类和对象。我们目前使用regasm
在注册表中注册COM 类。这已经工作了多年。
我们现在想摆脱 COM 注册并使用side by side assemblies。我目前正在尝试进行这种过渡,但我似乎在终点线上失败了。我们提供了一个使用我们的 COM 类的 C++ 示例应用程序,我尝试让它在没有 COM 注册的情况下运行。
.NET DLL
在我们的 .NET DLL 中,我有一个这样的类:
namespace MyNamespace
[ComVisible(true)]
[Guid("ef828ade-b459-4446-80db-956715588601")]
[ClassInterface(ClassInterfaceType.None)]
[ProgId("MyVendor.MyClass")]
public partial class MyClass
应用程序组装
应与该 COM 类一起使用的 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 类暴露给外界:
<?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 并创建类的实例:
HRESULT hr = CLSIDFromProgID(OLESTR("MyVendor.MyClass"), &clsid);
hr = CoCreateInstance(clsid, nullptr, CLSCTX_SERVER, IID_IDispatch, (void**)(&_pMyClass));
出了什么问题
我使用一些调试输出来检查从CLSIDFromProgID()
返回的 GUID 并检查返回值。如果 COM 类是使用regasm
注册的,则返回值为S_OK
,clsid
与我在 .NET DLL 中为该类指定的 GUID 相同。
但是,如果我删除 COM 注册并使用带有清单的并行程序集,如上所示,我也会得到 S_OK
返回值,但 GUID 完全不同,因此我无法创建这节课。我在任何地方都没有找到从 CLSIDFromProgID()
获得的 GUID - 无论是在注册表中还是在我的开发解决方案中。
你知道我做错了什么吗?
我知道我的 C++ 示例应用程序通常可以很好地处理我们的 COM 对象,因为如果注册了 COM 类,它就可以完美运行。 我检查了我使用 Microsoft's specification 和各种指南创建的清单的每个部分。 我在 Windows 事件日志中没有收到任何 SideBySide 错误,因此我知道清单格式正确。 我确实从CLSIDFromProgID()
得到了一个 S_OK
,所以我知道找到了 ProgID - 它只是提供了错误的 CLSID。
我使用函数StringFromCLSID()
来比较由`CLSIDFromProgID() 找到的CLSID。
【问题讨论】:
在调用CLSIDFromProgID()
时使用MyVendor.MyClass.1
而不是MyVendor.MyClass
是否也有同样的问题?或者如果您将清单中的progid
设置为MyVendor.MyClass
而不是MyVendor.MyClass.1
?
您的“COM”组件实际上是一个 .NET 程序集,对吗?您使用 comClass 而不是 clrClass 是否有原因?要通过清单向 COM 公开 .NET 程序集,我认为您应该改用 clrClass ???
Using .Net (CLR Managed) Classes in Win32 Applications | Using CLR managed classes in unmanaged win32 applications
使用 sysinternals 中的 Procmon,按注册表访问和您的 .exe 进行过滤,您应该会看到该 guid 的来源。
@Endgegner85 你看到这篇解释现象的文章了吗:manifestmaker.com/sxs/help/confclsid.htm
【参考方案1】:
首先,我要感谢 Joseph Willcoxson 和 Remy Lebeau 将我推向正确的方向!
我的清单中有几个小问题,我可以一个接一个地解决。我犯的一个大错误是假设我从 CLSIDFromProgID 获得的 CLSID 与我在 .NET COM 类中指定的 CLSID 相同。在指出不一定如此之后,我没有再浪费时间,并检查了调用 CoCreateInstance 失败的原因。它通过多次在线研究和测试来找出我犯的错误。
正如 Joseph 所指出的,我应该使用 clrClass 而不是 comClass。我在配置 clrClass 时犯了错误。例如,我为“name”使用了与“progId”相同的名称,但 clrClass 中的“name”是完整的命名空间 + 类名。
【讨论】:
以上是关于CLSIDFromProgID 返回错误的 prog id的主要内容,如果未能解决你的问题,请参考以下文章
013-ant design pro advanced 错误处理
当我尝试在 sequel pro 中运行此查询时出现错误 [重复]