无法从 C++ 中找到 COM 对象,尽管它已注册 Guid
Can't find COM object from C++, although Guid it's registered
首先祝大家新年快乐,希望你们一切顺利!
我正在开发一个 C++ 项目,我需要在其中调用我根据 this post 的第一个答案创建的 C# DLL。一旦我有了 DLL,我需要从 Qt 调用它,所以通过使用 dumpcpp 和由 regasm 生成的 .tlb 文件,我设法获取 .cpp 和 .h 文件以使用我的 classes。作为参考,classes 的命名空间是 Wrapper,而主要的 class 是 Device with guid {DD4A4896-C105-4C60-839B-B18C99C8FE15}.
一旦我生成了使用 DLL 的文件,如果我尝试在 Qt 上创建一个 Wrapper::Device 实例,我收到以下错误:
QAxBase::setControl: requested control {dd4a4896-c105-4c60-839b-b18c99c8fe15} could not be instantiated
QAxBase::qt_metacall: Object is not initialized, or initialization failed
它没有提供更多信息,所以我尝试检查 guid 是否存储在系统注册表中(我使用了前面引用的 post 中解释的 regasm 命令,它说它成功了,但你永远不知道)。打开注册表编辑器并搜索 Guid 显示它位于:Computer\HKEY_CLASSES_ROOT\WOW6432Node\CLSID\{DD4A4896-C105-4C60-839B-B18C99C8FE15}
,据我所知,这是这些 guid 的正确路径,它指向正确的 DLL。
我虽然这可能是由于某种 ActiveQt 问题,并且正如前面引用的 post 解释了如何从 VS C++ 使用该 DLL,我决定尝试一下,使用 this 作为另一个参考。我已经完成了这段代码,它应该创建我的 Device 对象的实例
#include <iostream>
#include <atlstr.h>
#import "C:\Users\javie\Documents\Wrapper\Wrapper\bin\x86\Release\netstandard2.0\Wrapper.tlb" named_guids raw_interfaces_only
inline void TESTHR(HRESULT x) { if FAILED(x) _com_issue_error(x); };
int main()
{
try
{
TESTHR(CoInitialize(0));
Wrapper::IDevicePtr devPtr = nullptr;
TESTHR(devPtr.CreateInstance("{DD4A4896-C105-4c60-839B-B18C99C8FE15}"));
}
catch (const _com_error& e)
{
CStringW out;
out.Format(L"Exception occurred. HR = %lx, error = %s", e.Error(), e.ErrorMessage());
MessageBoxW(NULL, out, L"Error", MB_OK);
}
CoUninitialize();// Uninitialize COM
std::cout << "Hello World!\n";
}
但是这样也不管用,createInstance方法抛出Class未注册和HR=80040154[=46的异常=].同样,根据注册表编辑器,class 已注册,所以我不明白这个错误。我还尝试使用 devPtr.CreateInstance("Wrapper.Device")
、devPtr.CreateInstance("Wrapper::Device")
或 `devPtr.CreateInstance("Wrapper::CLSID_Device") 作为我 posted 建议的链接,但在在那些情况下,我得到另一个异常 HR=800401f3 和消息 Invalid class string.
无论是否以管理员身份打开 VS 或 Qt Creator,我都会得到完全相同的错误。
我 运行 没有想法,我真的需要能够使用 dumpcpp 生成的文件从 Qt 使用该 DLL。
有人知道会发生什么吗?我觉得很奇怪。
如果您的 C++ 应用程序是 64 位的,这就是答案,因为您的 C# 组件是 32 位的(或 MSIL,但已注册到 32 位配置单元)。在这种情况下,使用 VBScript 进行简单测试总是有用的。
写一个简单的VB脚本(test.vbs)
Dim obj
Set obj = CreateObject("Wrapper.Device") ' or whatever your ProgID is
MsgBox TypeName(obj)
现在,运行 这个宏有 2 种方式:使用 32 位和 64 位版本的 VB脚本:
32-bit > c:\windows\SysWow64\cscript.exe test.vbs
64-bit > c:\windows\system32\cscript.exe test.vbs
这是假设您的 C# 组件是分派兼容的。如果不是,那么它仍然会给你不同的结果,你可以用来调试。
假设 automation/IDispatch 兼容,如果您正确注册了您的组件,一个可以工作,一个不能。
你注册正确了吗?当我使用 regasm 时,我总是在为 COM 注册 C# 组件时使用开关 /tlb /codebase。
好的,如果有人发现同样的错误,我会解释我找到的解决方案。
问题是,就我而言,我开发的 C# class 依赖于另一个未在我的 PC 上注册的 32 位 dll。一旦我注册了另一个 dll,一切正常。
我不知道为什么 VS 在我的 class 本身注册时一直告诉我 class 没有注册,这是它的一个依赖项没有注册。
总之,我发现这个要感谢 Joseph 的评论,非常感谢您的帮助。
首先祝大家新年快乐,希望你们一切顺利!
我正在开发一个 C++ 项目,我需要在其中调用我根据 this post 的第一个答案创建的 C# DLL。一旦我有了 DLL,我需要从 Qt 调用它,所以通过使用 dumpcpp 和由 regasm 生成的 .tlb 文件,我设法获取 .cpp 和 .h 文件以使用我的 classes。作为参考,classes 的命名空间是 Wrapper,而主要的 class 是 Device with guid {DD4A4896-C105-4C60-839B-B18C99C8FE15}.
一旦我生成了使用 DLL 的文件,如果我尝试在 Qt 上创建一个 Wrapper::Device 实例,我收到以下错误:
QAxBase::setControl: requested control {dd4a4896-c105-4c60-839b-b18c99c8fe15} could not be instantiated
QAxBase::qt_metacall: Object is not initialized, or initialization failed
它没有提供更多信息,所以我尝试检查 guid 是否存储在系统注册表中(我使用了前面引用的 post 中解释的 regasm 命令,它说它成功了,但你永远不知道)。打开注册表编辑器并搜索 Guid 显示它位于:Computer\HKEY_CLASSES_ROOT\WOW6432Node\CLSID\{DD4A4896-C105-4C60-839B-B18C99C8FE15}
,据我所知,这是这些 guid 的正确路径,它指向正确的 DLL。
我虽然这可能是由于某种 ActiveQt 问题,并且正如前面引用的 post 解释了如何从 VS C++ 使用该 DLL,我决定尝试一下,使用 this 作为另一个参考。我已经完成了这段代码,它应该创建我的 Device 对象的实例
#include <iostream>
#include <atlstr.h>
#import "C:\Users\javie\Documents\Wrapper\Wrapper\bin\x86\Release\netstandard2.0\Wrapper.tlb" named_guids raw_interfaces_only
inline void TESTHR(HRESULT x) { if FAILED(x) _com_issue_error(x); };
int main()
{
try
{
TESTHR(CoInitialize(0));
Wrapper::IDevicePtr devPtr = nullptr;
TESTHR(devPtr.CreateInstance("{DD4A4896-C105-4c60-839B-B18C99C8FE15}"));
}
catch (const _com_error& e)
{
CStringW out;
out.Format(L"Exception occurred. HR = %lx, error = %s", e.Error(), e.ErrorMessage());
MessageBoxW(NULL, out, L"Error", MB_OK);
}
CoUninitialize();// Uninitialize COM
std::cout << "Hello World!\n";
}
但是这样也不管用,createInstance方法抛出Class未注册和HR=80040154[=46的异常=].同样,根据注册表编辑器,class 已注册,所以我不明白这个错误。我还尝试使用 devPtr.CreateInstance("Wrapper.Device")
、devPtr.CreateInstance("Wrapper::Device")
或 `devPtr.CreateInstance("Wrapper::CLSID_Device") 作为我 posted 建议的链接,但在在那些情况下,我得到另一个异常 HR=800401f3 和消息 Invalid class string.
无论是否以管理员身份打开 VS 或 Qt Creator,我都会得到完全相同的错误。 我 运行 没有想法,我真的需要能够使用 dumpcpp 生成的文件从 Qt 使用该 DLL。
有人知道会发生什么吗?我觉得很奇怪。
如果您的 C++ 应用程序是 64 位的,这就是答案,因为您的 C# 组件是 32 位的(或 MSIL,但已注册到 32 位配置单元)。在这种情况下,使用 VBScript 进行简单测试总是有用的。
写一个简单的VB脚本(test.vbs)
Dim obj
Set obj = CreateObject("Wrapper.Device") ' or whatever your ProgID is
MsgBox TypeName(obj)
现在,运行 这个宏有 2 种方式:使用 32 位和 64 位版本的 VB脚本:
32-bit > c:\windows\SysWow64\cscript.exe test.vbs
64-bit > c:\windows\system32\cscript.exe test.vbs
这是假设您的 C# 组件是分派兼容的。如果不是,那么它仍然会给你不同的结果,你可以用来调试。
假设 automation/IDispatch 兼容,如果您正确注册了您的组件,一个可以工作,一个不能。
你注册正确了吗?当我使用 regasm 时,我总是在为 COM 注册 C# 组件时使用开关 /tlb /codebase。
好的,如果有人发现同样的错误,我会解释我找到的解决方案。 问题是,就我而言,我开发的 C# class 依赖于另一个未在我的 PC 上注册的 32 位 dll。一旦我注册了另一个 dll,一切正常。
我不知道为什么 VS 在我的 class 本身注册时一直告诉我 class 没有注册,这是它的一个依赖项没有注册。
总之,我发现这个要感谢 Joseph 的评论,非常感谢您的帮助。