REGDB_E_CLASSNOTREG
表示您要求的类(无论是 COM/WinRT 等)未注册/激活系统(托管在 combase.dll 中)。
问题可能来自您尝试使用免注册 WinRT 组件这一事实。
让我们将此示例作为 C# 组件的开始:演练:创建 C#/WinRT 组件并从 C++/WinRT 使用它。因此,只需创建 C# 组件,不要创建 C++/WinRT 应用程序。(我使用 Visual Studio 2019 和 net5.0-windows10.0.19041.0)。
注意:C#/WinRT 会生成 .dll(此处为SampleComponent.dll
),而不仅仅是元数据。
如果不构建 C++/WinRT 应用程序,仍需要构建常规 .h 文件才能使用 C# 组件。C++/WinRT 会为您完成这项工作,但由于我们不使用此工具,因此我们必须自己构建它。为此,我们需要另外两个工具winmdidl.exe
,midlrt.exe
您可以从Visual Studio 的开发人员命令提示符中找到它们。.另
请参阅如何:使用 winmdidl.exe 和 midlrt.exe 从 Windows 元数据创建 .h 文件
因此,SampleComponent.winmd
如果您按照本教程进行操作,请运行:
winmdidl SampleComponent.winmd
这将创建一个SampleComponent.idl
文件。现在运行:
midlrt SampleComponent.idl /metadata_dir "C:\Windows\System32\WinMetadata"
这将创建多个文件(代理、存根等),但我们只需要SampleComponent.h
. 现在,创建一个像这样的标准 C++ 控制台应用程序(我不使用 C++/WinRT,我仍然使用它Wrl
来简化我的代码,但这不是强制性的):
#include <windows.h>
#include <stdio.h>
#include <wrl.h>
#include <wrl/wrappers/corewrappers.h>
#include "path to SampleComponent.h"
#pragma comment(lib, "runtimeobject.lib")
using namespace Microsoft::WRL; // ComPtr
using namespace Microsoft::WRL::Wrappers; // RoInitializeWrapper, HStringReference, HString
using namespace Windows::Foundation; // GetActivationFactory, ActivateInstance
int main()
{
RoInitializeWrapper init(RO_INIT_MULTITHREADED);
HRESULT hr = init;
// all error checks on hr omitted
ComPtr<SampleComponent::IExampleClass> cls;
hr = ActivateInstance(HStringReference(RuntimeClass_SampleComponent_Example).Get(), &cls);
hr = cls->put_SampleProperty(42);
INT32 i;
hr = cls->get_SampleProperty(&i);
wprintf(L"%u\n", i);
ComPtr<SampleComponent::IExampleStatic> clsStatic;
hr = GetActivationFactory(HStringReference(RuntimeClass_SampleComponent_Example).Get(), &clsStatic);
HString str;
hr = clsStatic->SayHello(str.GetAddressOf());
wprintf(L"%s\n", str.GetRawBuffer(nullptr));
}
RuntimeClass_SampleComponent_Example
来自SampleComponent.h
并且应该像这样定义:
extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_SampleComponent_Example[] = L"SampleComponent.Example";
如果你编译它并运行,hr 将是REGDB_E_CLASSNOTREG
因为系统找不到该'SampleComponent.Example'
组件。
所以你必须做的在这里解释:免注册 WinRT 的工作原理
您必须向项目中添加一个带有.manifest
扩展名的文件(任何名称都应该适用于最新版本的 Visual Studio),例如:
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity version="1.0.0.0" name="CppConsoleApp"/>
<file name="WinRT.Host.dll">
<activatableClass
name="SampleComponent.Example"
threadingModel="both"
xmlns="urn:schemas-microsoft-com:winrt.v1" />
</file>
</assembly>
assemblyIdentity
'sname
不是很重要,最重要的是file
and activatableClass
's name
:它必须与主机 dll 名称(这里它必须WinRT.Host.dll
由 C#/WinRT 提供)和您尝试激活的类名相同(对应到RuntimeClass_SampleComponent_Example
)。
您还必须将所有需要的 C#/WinRT 文件复制到.exe文件旁边。那将是: SampleComponent.dll
, Microsoft.Windows.SDK.NET.dll
, WinRT.Host.dll
, WinRT.Host.runtimeconfig.json
, WinRT.Host.Shim.dll
, WinRT.Runtime.dll
。
请注意,您可以使用 C++/WinRT 来帮助构建WinRT.Host.runtimeconfig.json
.
现在,它应该可以工作了。