Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Sie können die Windows-Runtime C++-Vorlagenbibliothek (WRL) verwenden, um grundlegende klassische COM-Komponenten für die Verwendung in Desktop-Apps zu erstellen, zusätzlich zur Verwendung für Universelle Windows-Plattform(UWP)-Apps. Für die Erstellung von COM-Komponenten benötigt die Windows-Runtime C++-Vorlagenbibliothek möglicherweise weniger Code als die ATL. Informationen zur Teilmenge von COM, die von der Windows-Runtime C++-Vorlagenbibliothek unterstützt wird, finden Sie unter Windows-Runtime C++-Vorlagenbibliothek (WRL).
Dieses Dokument zeigt, wie Sie die Windows-Runtime C++-Vorlagenbibliothek verwenden, um eine einfache COM-Komponente zu erstellen. Obwohl Sie den Bereitstellungsmechanismus, der für Ihre Anforderungen am besten geeignet ist, verwenden können, zeigt dieses Dokument auch eine einfache Möglichkeit zur Registrierung und Nutzung der COM-Komponente aus einer Desktop-App.
So verwenden Sie die Windows-Runtime C++-Vorlagenbibliothek zum Erstellen einer einfachen klassischen COM-Komponente
Erstellen Sie in Visual Studio ein leeres Projektmappenprojekt . Geben Sie dem Projekt einen Namen,
WRLClassicCOM
z. B. .Fügen Sie der Projektmappe ein Win32-Projekt hinzu. Geben Sie dem Projekt einen Namen,
CalculatorComponent
z. B. . Wählen Sie auf der Registerkarte "Anwendungseinstellungen" DIE DLL-Datei aus.Fügen Sie dem Projekt eine Midl-Dateidatei (IDL) hinzu. Nennen Sie die Datei, z. B
CalculatorComponent.idl
. .Fügen Sie diesen Code zu CalculatorComponent.idl hinzu:
import "ocidl.idl"; [uuid(0DBABB94-CE99-42F7-ACBD-E698B2332C60), version(1.0)] interface ICalculatorComponent : IUnknown { HRESULT Add([in] int a, [in] int b, [out, retval] int* value); } [uuid(9D3E6826-CB8E-4D86-8B14-89F0D7EFCD01), version(1.0)] library CalculatorComponentLib { [uuid(E68F5EDD-6257-4E72-A10B-4067ED8E85F2), version(1.0)] coclass CalculatorComponent { [default] interface ICalculatorComponent; } };
Definieren Sie die
CalculatorComponent
Klasse in CalculatorComponent.cpp. DieCalculatorComponent
Klasse erbt von Microsoft::WRL::RuntimeClass. Microsoft::WRL::RuntimeClassFlags<ClassicCom> gibt an, dass die Klasse von IUnknown und nicht von IInspectable abgeleitet wird. (IInspectable
ist nur für Windows-Runtime App-Komponenten verfügbar.)CoCreatableClass
erstellt eine Factory für die Klasse, die mit Funktionen wie CoCreateInstance verwendet werden kann.#include "pch.h" // Use stdafx.h in Visual Studio 2017 and earlier #include "CalculatorComponent_h.h" #include <wrl.h> using namespace Microsoft::WRL; class CalculatorComponent: public RuntimeClass<RuntimeClassFlags<ClassicCom>, ICalculatorComponent> { public: CalculatorComponent() { } STDMETHODIMP Add(_In_ int a, _In_ int b, _Out_ int* value) { *value = a + b; return S_OK; } }; CoCreatableClass(CalculatorComponent);
Verwenden Sie den folgenden Code, um den Code in
dllmain.cpp
. Diese Datei definiert die DLL-Exportfunktionen. Diese Funktionen verwenden die Microsoft::WRL::Module-Klasse , um die Klassenfabriken für das Modul zu verwalten.#include "pch.h" // Use stdafx.h in Visual Studio 2017 and earlier #include <wrl\module.h> using namespace Microsoft::WRL; #if !defined(__WRL_CLASSIC_COM__) STDAPI DllGetActivationFactory(_In_ HSTRING activatibleClassId, _COM_Outptr_ IActivationFactory** factory) { return Module<InProc>::GetModule().GetActivationFactory(activatibleClassId, factory); } #endif #if !defined(__WRL_WINRT_STRICT__) STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, _COM_Outptr_ void** ppv) { return Module<InProc>::GetModule().GetClassObject(rclsid, riid, ppv); } #endif STDAPI DllCanUnloadNow() { return Module<InProc>::GetModule().Terminate() ? S_OK : S_FALSE; } STDAPI_(BOOL) DllMain(_In_opt_ HINSTANCE hinst, DWORD reason, _In_opt_ void*) { if (reason == DLL_PROCESS_ATTACH) { DisableThreadLibraryCalls(hinst); } return TRUE; }
Fügen Sie dem Projekt eine Moduldefinitionsdatei (.def) hinzu. Nennen Sie die Datei, z. B
CalculatorComponent.def
. . Diese Datei gibt dem Linker die Namen der zu exportierenden Funktionen. Öffnen Sie das Dialogfeld "Eigenschaftenseiten" für Ihr Projekt, und legen Sie dann unter "Konfigurationseigenschaftenverknüpfungseingabe>>" die Eigenschaft "Moduldefinitionsdatei" auf Ihre DEF-Datei fest.Fügen Sie diesen Code zu CalculatorComponent.def hinzu:
LIBRARY EXPORTS DllGetActivationFactory PRIVATE DllGetClassObject PRIVATE DllCanUnloadNow PRIVATE
Der Linker-Befehlszeile runtimeobject.lib hinzufügen. Informationen dazu finden Sie unter
.Lib
"Dateien als Linkereingabe".
Nutzen Sie die COM-Komponente aus einer Desktop-App.
Registrieren Sie die COM-Komponente mit der Windows-Registrierung. Erstellen Sie dazu eine Registrierungseintragsdatei, nennen Sie sie
RegScript.reg
, und fügen Sie den folgenden Text hinzu. Ersetzen Sie <dll-Pfad> durch den Pfad Ihrer DLL,C:\temp\WRLClassicCOM\Debug\CalculatorComponent.dll
z. B. .Windows Registry Editor Version 5.00 [HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{E68F5EDD-6257-4E72-A10B-4067ED8E85F2}] @="CalculatorComponent Class" [HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{E68F5EDD-6257-4E72-A10B-4067ED8E85F2}\InprocServer32] @="<dll-path>" "ThreadingModel"="Apartment" [HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{E68F5EDD-6257-4E72-A10B-4067ED8E85F2}\Programmable] [HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{E68F5EDD-6257-4E72-A10B-4067ED8E85F2}\TypeLib] @="{9D3E6826-CB8E-4D86-8B14-89F0D7EFCD01}" [HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{E68F5EDD-6257-4E72-A10B-4067ED8E85F2}\Version] @="1.0"
Führen Sie RegScript.reg aus, oder fügen Sie es dem Post-Build-Ereignis Ihres Projekts hinzu. Weitere Informationen finden Sie im Dialogfeld "Vorabbuildereignis/Postbuildereignis".
Fügen Sie der Projektmappe ein Win32-Konsolenanwendungsprojekt hinzu. Geben Sie dem Projekt einen Namen,
Calculator
z. B. .Verwenden Sie diesen Code, um den Inhalt von
Calculator.cpp
:#include "pch.h" // Use stdafx.h in Visual Studio 2017 and earlier #include "..\CalculatorComponent\CalculatorComponent_h.h" const IID IID_ICalculatorComponent = {0x0DBABB94,0xCE99,0x42F7,0xAC,0xBD,0xE6,0x98,0xB2,0x33,0x2C,0x60}; const CLSID CLSID_CalculatorComponent = {0xE68F5EDD,0x6257,0x4E72,0xA1,0x0B,0x40,0x67,0xED,0x8E,0x85,0xF2}; // Prints an error string for the provided source code line and HRESULT // value and returns the HRESULT value as an int. int PrintError(unsigned int line, HRESULT hr) { wprintf_s(L"ERROR: Line:%d HRESULT: 0x%X\n", line, hr); return hr; } int wmain() { HRESULT hr; // Initialize the COM library. hr = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); if (FAILED(hr)) { return PrintError(__LINE__, hr); } ICalculatorComponent* calc = nullptr; // Interface to COM component. // Create the CalculatorComponent object. hr = CoCreateInstance(CLSID_CalculatorComponent, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&calc)); if (SUCCEEDED(hr)) { // Test the component by adding two numbers. int result; hr = calc->Add(4, 5, &result); if (FAILED(hr)) { PrintError(__LINE__, hr); } else { wprintf_s(L"result = %d\n", result); } // Free the CalculatorComponent object. calc->Release(); } else { // Object creation failed. Print a message. PrintError(__LINE__, hr); } // Free the COM library. CoUninitialize(); return hr; } /* Output: result = 9 */
Stabile Programmierung
In diesem Dokument werden standardmäßige COM-Funktionen verwendet, um zu veranschaulichen, dass Sie die Windows-Runtime C++-Vorlagenbibliothek verwenden können, um eine COM-Komponente zu erstellen und für jede COM-fähige Technologie verfügbar zu machen. Sie können auch Windows-Runtime C++-Vorlagenbibliothekstypen wie Microsoft::WRL::ComPtr in Ihrer Desktop-App verwenden, um die Lebensdauer von COM und anderen Objekten zu verwalten. Der folgende Code verwendet die Windows-Runtime C++-Vorlagenbibliothek, um die Lebensdauer des ICalculatorComponent
Zeigers zu verwalten. Die CoInitializeWrapper
Klasse ist ein RAII-Wrapper, der sicherstellt, dass die COM-Bibliothek freigegeben wird und dass die Lebensdauer der COM-Bibliothek länger ist als die vom ComPtr
intelligenten Zeiger-Objekt.
#include "pch.h" // Use stdafx.h in Visual Studio 2017 and earlier
#include <wrl.h>
#include "..\CalculatorComponent\CalculatorComponent_h.h"
using namespace Microsoft::WRL;
const IID IID_ICalculatorComponent = {0x0DBABB94,0xCE99,0x42F7,0xAC,0xBD,0xE6,0x98,0xB2,0x33,0x2C,0x60};
const CLSID CLSID_CalculatorComponent = {0xE68F5EDD,0x6257,0x4E72,0xA1,0x0B,0x40,0x67,0xED,0x8E,0x85,0xF2};
// Prints an error string for the provided source code line and HRESULT
// value and returns the HRESULT value as an int.
int PrintError(unsigned int line, HRESULT hr)
{
wprintf_s(L"ERROR: Line:%d HRESULT: 0x%X\n", line, hr);
return hr;
}
int wmain()
{
HRESULT hr;
// RAII wrapper for managing the lifetime of the COM library.
class CoInitializeWrapper
{
HRESULT _hr;
public:
CoInitializeWrapper(DWORD flags)
{
_hr = CoInitializeEx(nullptr, flags);
}
~CoInitializeWrapper()
{
if (SUCCEEDED(_hr))
{
CoUninitialize();
}
}
operator HRESULT()
{
return _hr;
}
};
// Initialize the COM library.
CoInitializeWrapper initialize(COINIT_APARTMENTTHREADED);
if (FAILED(initialize))
{
return PrintError(__LINE__, initialize);
}
ComPtr<ICalculatorComponent> calc; // Interface to COM component.
// Create the CalculatorComponent object.
hr = CoCreateInstance(CLSID_CalculatorComponent, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(calc.GetAddressOf()));
if (SUCCEEDED(hr))
{
// Test the component by adding two numbers.
int result;
hr = calc->Add(4, 5, &result);
if (FAILED(hr))
{
return PrintError(__LINE__, hr);
}
wprintf_s(L"result = %d\n", result);
}
else
{
// Object creation failed. Print a message.
return PrintError(__LINE__, hr);
}
return 0;
}