Condividi tramite


Procedura: creare un componente COM classico mediante WRL

È possibile utilizzare Libreria di modelli di Windows Runtime C++ (WRL) per creare componenti COM classiche di base per l'utilizzo in applicazioni desktop, oltre a utilizzare per le applicazioni di Windows Store.Per la creazione di componenti COM, WRL può richiedere meno codice che ATL.Per informazioni sul sottoinsieme di COM che supporta di WRL, vedere a Libreria di modelli di Windows Runtime C++ (WRL).

In questo documento viene illustrato come utilizzare WRL per creare un componente COM base.Sebbene sia possibile utilizzare il meccanismo di distribuzione che meglio adatta alle proprie esigenze, questo documento viene illustrato un metodo di base registrare e utilizzare il componente COM da un'applicazione desktop.

Per utilizzare WRL per creare un componente COM classico di base

  1. In Visual Studio, creare un progetto Soluzione vuota.Denominare il progetto, ad esempio, WRLClassicCOM.

  2. Aggiungere Progetto Win32 alla soluzione.Denominare il progetto, ad esempio, CalculatorComponent.Nella scheda Impostazioni applicazione, dllselezionato.

  3. Aggiungere un file File Midl (.idl) al progetto.Denominare il file, ad esempio, CalculatorComponent.idl.

  4. Aggiungere questo codice a 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. In CalculatorComponent.cpp, definire la classe di CalculatorComponent.La classe di CalculatorComponent eredita da Microsoft::WRL::RuntimeClass.Microsoft::WRL::RuntimeClassFlags<ClassicCom> specifica che la classe deriva da IUnknown e non IInspectable.(IInspectable è disponibile solo ai componenti dell'applicazione di Store ). CoCreatableClass crea una factory per la classe utilizzabile con funzioni quali. 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. Utilizzare il codice per sostituire il codice in dllmain.cpp.Questo file definisce le funzioni di esportazione di DLL.Queste funzioni utilizzano la classe di Microsoft::WRL::Module per gestire i class factory per il modulo.

    #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. Aggiungere un file File di definizione moduli (.def) al progetto.Denominare il file, ad esempio, CalculatorComponent.def.Questo file fornisce al linker i nomi delle funzioni da esportare.

  8. Aggiungere questo codice a CalculatorComponent.def:

    LIBRARY
    
    EXPORTS
        DllGetActivationFactory PRIVATE
        DllGetClassObject       PRIVATE
        DllCanUnloadNow         PRIVATE
    
  9. Aggiungere runtimeobject.lib alla riga di comando del linker.Per informazioni su, vedere File lib come input del linker.

Per utilizzare il componente COM da un'applicazione desktop

  1. Registrare il componente COM con Registro di sistema di Windows.A tale scopo, creare un file di voci di registrazione, denominarlo RegScript.rege aggiungere il seguente testo.<dll-path> di sostituire con il percorso della dll, ad esempio 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. Eseguire RegScript.reg oppure aggiungerlo a Evento di post-compilazionedel progetto.Per ulteriori informazioni, vedere Finestra di dialogo Riga di comando eventi pre-compilazione/post-compilazione.

  3. Aggiungere un progetto Progetto console Win32 alla soluzione.Denominare il progetto, ad esempio, La calcolatrice.

  4. Utilizzare questo codice per sostituire il contenuto di 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
    */
    

Programmazione efficiente

In questo documento vengono utilizzate le funzioni standard COM per dimostrare che è possibile utilizzare WRL per creare un componente COM e per metterla disponibili per qualsiasi tecnologia abilitata COM.È inoltre possibile utilizzare i tipi di WRL come Microsoft::WRL::ComPtr nell'applicazione desktop per gestire la durata di COM e di altri oggetti.Nel codice riportato WRL per gestire la durata del puntatore di ICalculatorComponent.La classe di CoInitializeWrapper è un wrapper RAII che garantisce che la libreria COM viene liberata e anche garanzie che la durata della libreria COM sopravvive l'oggetto del puntatore intelligente di ComPtr.

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

Vedere anche

Concetti

Libreria di modelli di Windows Runtime C++ (WRL)