我有一個現有的程式 win32 (x86) 控制臺應用程式,它需要呼叫托管代碼(來自 .Net 的 C# .dll)。在.dll不暴露于COM,但可以從一個C#/ WinRT的組件呼叫和C / WinRT的控制臺模板的應用程式參考,但我似乎無法即使安裝了C / WinRT中的NuGet之后,從一個Win32 x86的控制臺應用程式呼叫它包裹。我已經構建并運行了
按照 Simon 的回復,我能夠創建一個可以從 Win32 控制臺應用程式呼叫的 C# WinRT 組件。這個 C# WinRT 組件確實輸出 .dll 和 .winmd。我更接近于Simon 發表的關于使用 C 進行消費的文章,并設法讓它與基本的 C# 函式一起作業。
uj5u.com熱心網友回復:
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 is from SampleComponent.h and should be defined like this:
extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_SampleComponent_Example[] = L"SampleComponent.Example";
If you compile that and run, hr will be REGDB_E_CLASSNOTREG because the system cannot find the 'SampleComponent.Example' component.
So what you must do is explained here: How Registration-free WinRT Works
You must add a file to the project with the .manifest extension (any name should work with recent versions of Visual Studio), for example like this:
<?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's name is not super important, what is super important is file and activatableClass's name: it must be the same as the host dll name (here it must be WinRT.Host.dll which is provided by C#/WinRT) and class name you're trying to activate (corresponding to RuntimeClass_SampleComponent_Example).
You must also copy all the C#/WinRT files mess needed aside your .exe file. That would be : SampleComponent.dll, Microsoft.Windows.SDK.NET.dll, WinRT.Host.dll, WinRT.Host.runtimeconfig.json, WinRT.Host.Shim.dll, WinRT.Runtime.dll.
Note you can use C /WinRT to help building WinRT.Host.runtimeconfig.json.
And now, it should work.
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/314749.html
上一篇:移動到不同的螢屏時,MoveWindow不會縮放視窗
下一篇:創建支持基于范圍迭代的COM指標
