Postupy: Vytvoření klasické komponenty COM s použitím knihovny WRL

Knihovnu šablon jazyka C++ (WRL) prostředí Windows Runtime můžete použít k vytvoření základních klasických komponent modelu COM pro použití v desktopových aplikacích, a to i pro aplikace pro Univerzální platforma Windows (UPW). Při vytváření komponent modelu COM může knihovna šablon jazyka C++ prostředí Windows Runtime vyžadovat méně kódu než KNIHOVNA ATL. Informace o podmnožině modelu COM, kterou knihovna šablon jazyka C++ prostředí Windows Runtime jazyka C++podporuje, najdete v tématu prostředí Windows Runtime knihovna šablon jazyka C++ (WRL).

Tento dokument ukazuje, jak pomocí knihovny šablon jazyka C++ prostředí Windows Runtime vytvořit základní komponentu MODELU COM. I když můžete použít mechanismus nasazení, který nejlépe vyhovuje vašim potřebám, tento dokument také ukazuje základní způsob registrace a využívání komponenty MODELU COM z desktopové aplikace.

Použití knihovny šablon jazyka prostředí Windows Runtime C++ k vytvoření základní klasické komponenty MODELU COM

  1. V sadě Visual Studio vytvořte prázdný projekt řešení . Pojmenujte projekt, například WRLClassicCOM.

  2. Přidejte do řešení projekt Win32. Pojmenujte projekt, například CalculatorComponent. Na kartě Nastavení aplikace vyberte knihovnu DLL.

  3. Přidejte do projektu soubor Midl (.idl). Pojmenujte soubor, například CalculatorComponent.idl.

  4. Přidejte tento kód 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. V souboru CalculatorComponent.cpp definujte CalculatorComponent třídu. Třída CalculatorComponent dědí z Microsoft::WRL::RuntimeClass. Microsoft::WRL::RuntimeClassFlags<ClassicCom> určuje, že třída je odvozena od IUnknown a není IInspectable. (IInspectable je k dispozici pouze pro prostředí Windows Runtime komponenty aplikace.) CoCreatableClass vytvoří továrnu pro třídu, kterou lze použít s funkcemi, jako je CoCreateInstance.

    #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);
    
  6. Pomocí následujícího kódu nahraďte kód v dllmain.cppsouboru . Tento soubor definuje funkce exportu knihovny DLL. Tyto funkce používají třídu Microsoft::WRL::Module ke správě továren tříd pro modul.

    #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;
    }
    
  7. Přidejte do projektu soubor souboru .def (Module-Definition File). Pojmenujte soubor, například CalculatorComponent.def. Tento soubor poskytuje linkeru názvy funkcí, které se mají exportovat. Otevřete dialogové okno Stránky vlastností projektu a pak v části Vstup linkeru> Vlastností>konfigurace nastavte vlastnost Soubor definice modulu na váš soubor DEF.

  8. Přidejte tento kód do calculatorComponent.def:

    LIBRARY
    
    EXPORTS
        DllGetActivationFactory PRIVATE
        DllGetClassObject       PRIVATE
        DllCanUnloadNow         PRIVATE
    
  9. Přidejte modul runtimeobject.lib na řádek linkeru. Postup najdete v tématu .Lib Soubory jako vstup linkeru.

Využití komponenty MODELU COM z desktopové aplikace

  1. Zaregistrujte komponentu COM v registru Systému Windows. Uděláte to tak, že vytvoříte soubor s položkami registrace, pojmenujte ho RegScript.rega přidejte následující text. Nahraďte <cestu> dll cestou k vaší knihovně DLL, C:\temp\WRLClassicCOM\Debug\CalculatorComponent.dllnapříklad .

    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. Spusťte RegScript.reg nebo ho přidejte do události post-buildu projektu. Další informace najdete v tématu Událost před sestavením / Dialogové okno příkazového řádku události po sestavení.

  3. Přidejte do řešení projekt konzolové aplikace Win32. Pojmenujte projekt, například Calculator.

  4. Tento kód slouží k nahrazení obsahu 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
    */
    

Robustní programování

Tento dokument používá standardní funkce modelu COM k předvedení, že můžete použít prostředí Windows Runtime knihovnu šablon jazyka C++ k vytvoření komponenty modelu COM a zpřístupnit ji libovolné technologii s podporou modelu COM. Ke správě doby života modelu COM a dalších objektů můžete použít také prostředí Windows Runtime typy knihovny šablon jazyka C++, například Microsoft::WRL::ComPtr v desktopové aplikaci. Následující kód používá prostředí Windows Runtime knihovnu šablon jazyka C++ ke správě životnosti ICalculatorComponent ukazatele. Třída CoInitializeWrapper je obálka RAII, která zaručuje, že knihovna COM je uvolněna, a také zaručuje, že životnost knihovny COM prožije objekt inteligentního ComPtr ukazatele.

#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;
}

Viz také

Knihovna šablon C++ prostředí Windows Runtime (WRL)