Comment : créer un composant COM classique à l'aide de WRL

Vous pouvez utiliser Bibliothèque de modèles Windows Runtime C++ (WRL) pour créer des composants COM classiques de base à utiliser dans les applications de bureau, en plus de utiliser pour les applications d' Windows Store .Pour la création de composants COM, WRL peut nécessiter moins de code qu'ATL.Pour plus d'informations sur le sous-ensemble COM qui prend en charge d' WRL, consultez à Bibliothèque de modèles Windows Runtime C++ (WRL).

Ce document montre comment utiliser WRL pour créer un composant COM de base.Bien que vous puissiez utiliser le mécanisme de déploiement que les mieux à vos besoins, ce document montre également à une méthode de base pour stocker et utiliser le composant COM d'une application de bureau.

Pour utiliser WRL pour créer un composant COM classique de base

  1. Dans Visual Studio, créez un projet de Nouvelle solution .Nommez le projet, par exemple, WRLClassicCOM.

  2. Ajoutez Projet Win32 à la solution.Nommez le projet, par exemple, CalculatorComponent.Sous l'onglet de Paramètres de l'application, sélectionnez DLL.

  3. Ajoutez un fichier Fichier Midl (.idl) au projet.Nommez le fichier, par exemple, CalculatorComponent.idl.

  4. Ajoutez ce code à 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. Dans CalculatorComponent.cpp, définissez la classe d' CalculatorComponent .La classe d' CalculatorComponent hérite d' Microsoft::WRL::RuntimeClass.Microsoft::WRL::RuntimeClassFlags<ClassicCom> spécifie que la classe dérive de IUnknown et non IInspectable.(IInspectable est disponible uniquement aux composants d'application d' Store .) CoCreatableClass crée une fabrique pour la classe comme CoCreateInstancelaquelle peut être utilisé avec des fonctions.

    #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. Utilisez le code suivant pour remplacer le code dans dllmain.cpp.Ce fichier définit les fonctions d'exportation de DLL.Ces fonctions utilisent la classe d' Microsoft::WRL::Module pour gérer les fabriques de classe pour le package.

    #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. Ajoutez un fichier Fichier de définition de module (.def) au projet.Nommez le fichier, par exemple, CalculatorComponent.def.Ce fichier fournit à l'éditeur de liens les noms des fonctions à exporter.

  8. Ajoutez ce code à CalculatorComponent.def :

    LIBRARY
    
    EXPORTS
        DllGetActivationFactory PRIVATE
        DllGetClassObject       PRIVATE
        DllCanUnloadNow         PRIVATE
    
  9. Ajoutez runtimeobject.lib à la ligne de l'éditeur de liens.Pour savoir comment, consultez .Fichiers .lib en tant qu'entrée de l'Éditeur de liens.

Pour utiliser le composant COM d'une application de bureau

  1. Enregistrez le composant COM avec le Registre Windows.Pour cela, créez un fichier d'entrée d'inscription, le nom RegScript.reg, et ajouter le texte suivant.Remplacez <dll-path> par le chemin d'accès de votre DLL- pour l'exemple, 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. Exécutez RegScript.reg ou ajoutez-le à Événement post-buildde votre projet.Pour plus d'informations, consultez Ligne de commande de l'événement pré-build/post-build, boîte de dialogue.

  3. Ajoutez un projet de Application console Win32 à la solution.Nommez le projet, par exemple, Calculator.

  4. Utilisez ce code pour remplacer le contenu de 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
    */
    

Programmation fiable

Ce document utilise des fonctions standard COM pour montrer que vous pouvez utiliser WRL pour créer un composant COM et le rendre disponible pour toute technologie COM activée.Vous pouvez également utiliser des types d' WRL tels qu' Microsoft::WRL::ComPtr dans votre application de bureau pour gérer la durée de vie COM et d'autres objets.Le code suivant utilise WRL pour gérer la durée de vie du pointeur d' ICalculatorComponent .La classe d' CoInitializeWrapper est un wrapper RAII qui garantit que la bibliothèque COM est libérée et également des garanties que la durée de vie de la bibliothèque COM survit à l'objet de pointeur intelligent d' 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;
}

Voir aussi

Concepts

Bibliothèque de modèles Windows Runtime C++ (WRL)