Udostępnij za pośrednictwem


Porady: tworzenie klasycznego składnika COM za pomocą biblioteki WRL

Można użyć Biblioteka szablonów C++ środowiska wykonawczego systemu Windows (WRL) do tworzenia podstawowych składników modelu COM do użycia w aplikacji pulpitu, dodatkowo do korzystania z niej dla Windows Store aplikacji.Tworzenie składników COM WRL może wymagać mniejszej ilości kodu niż ATLAby uzyskać informacje dotyczące podzbioru COM, WRL podpory, zobacz Biblioteka szablonów języka C++ środowiska wykonawczego systemu Windows (WRL).

Ten dokument pokazuje sposób używania WRL do utworzenia podstawowego składnika modelu COM.Chociaż można używać mechanizm wdrażania, która najlepiej odpowiada Twoim potrzebom, ten dokument pokazuje również podstawowy sposób, aby zarejestrować i zużywają składnika modelu COM z aplikacji pulpitu.

Aby użyć WRL do utworzenia podstawowego składnika klasycznego modelu COM

  1. W programie Visual Studio, tworzenie Roztwór próby ślepej projektu.Nazwa projektu, na przykład, WRLClassicCOM.

  2. Dodać Projekt systemu Win32 do roztworu.Nazwa projektu, na przykład, CalculatorComponent.Na Ustawienia aplikacji kartę, a następnie kliknij polecenie Wybierz DLL.

  3. Dodać Plik regionów (.idl) plik do projektu.Nazwę pliku, na przykład, CalculatorComponent.idl.

  4. Dodaj ten kod do CalculatorComponent.idl:

    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;
        }
    };
    
  5. W CalculatorComponent.cpp, zdefiniuj CalculatorComponent klasy.CalculatorComponent Klasa dziedziczy z Microsoft::WRL::RuntimeClass.Microsoft::WRL::RuntimeClassFlags <ClassicCom> Określa, że klasa pochodzi od IUnknown i nie IInspectable.(IInspectable jest dostępna tylko dla Store składników aplikacji.) CoCreatableClass tworzy fabryki dla klasy, która może być używany z funkcji takich jak Wywołanie funkcji CoCreateInstance.

    #include "stdafx.h"
    
    #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)
        {
            if (value == nullptr)
            {
                return E_POINTER;
            }
            *value = a + b;
            return S_OK;
        }
    };
    
    CoCreatableClass(CalculatorComponent);
    
  6. Użyć następującego kodu, aby zastąpić kod w dllmain.cpp.Ten plik definiuje funkcje eksportu biblioteki DLL.Te funkcje za pomocą Microsoft::WRL::Module klasy do zarządzania fabryk klas dla modułu.

    #include "stdafx.h"
    #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;
    }
    
  7. Dodać Pliku definicji modułów (o rozszerzeniu def) plik do projektu.Nazwę pliku, na przykład, CalculatorComponent.def.Ten plik zawiera program łączący nazwy funkcji, które mają zostać wywiezione.

  8. Dodaj ten kod do CalculatorComponent.def:

    LIBRARY
    
    EXPORTS
        DllGetActivationFactory PRIVATE
        DllGetClassObject       PRIVATE
        DllCanUnloadNow         PRIVATE
    
  9. Dodaj runtimeobject.lib do linii programu łączącego.Aby dowiedzieć się, jak to zrobić, zobacz .Pliki lib jako dane wejściowe Linker.

Do spożywania składnika modelu COM z aplikacji pulpitu

  1. Zarejestruj składnik COM z rejestru systemu Windows.W tym celu należy utworzyć plik wpisów rejestracji, nadaj mu nazwę RegScript.regi Dodaj następujący tekst.Zamień < - ścieżka do biblioteki dll > ze ścieżką biblioteki DLL — na przykład, C:\\temp\\WRLClassicCOM\\Debug\\CalculatorComponent.dll.

    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"
    
  2. Uruchomić RegScript.reg lub dodać do swojego projektu Przypadku Post-Build.Aby uzyskać więcej informacji, zobacz Zdarzenie/występującymi-build zdarzeń wiersza polecenia okno dialogowe Pre-Build.

  3. Dodać Win32 Console Application projektu do rozwiązania.Nazwa projektu, na przykład, Kalkulator.

  4. Użyj tego numeru, aby zastąpić zawartość Calculator.cpp:

    #include "stdafx.h"
    
    #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_ICalculatorComponent, reinterpret_cast<void**>(&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
    */
    

Stabilne programowanie

Ten dokument używa standardowych funkcji COM do wykazania, że można używać WRL do Autor składnika modelu COM i udostępnić go do dowolnej z obsługą COM technologii.Można również użyć WRL typów, takich jak Microsoft::WRL::ComPtr w swojej aplikacji pulpitu, aby zarządzać okresem istnienia COM i inne obiekty.Następujący kod dodaje do zastosowań WRL do zarządzania istnienia ICalculatorComponent wskaźnik.CoInitializeWrapper Klasa jest otoką RAII, który gwarantuje, że biblioteki COM jest zwalniany, a także gwarantuje, że okres istnienia biblioteki COM przeżywają ComPtr obiektu inteligentnego wskaźnika.

#include "stdafx.h"
#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_ICalculatorComponent, reinterpret_cast<void**>(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;
}

Zobacz też

Koncepcje

Biblioteka szablonów języka C++ środowiska wykonawczego systemu Windows (WRL)