다음을 통해 공유


방법: WRL을 사용하여 기본 COM 구성 요소 만들기

사용할 수 있는 Windows 런타임 C++ 템플릿 라이브러리 (WRL)를 사용 하 여 또한 클래식 기본 COM 구성 요소에서 데스크톱 응용 프로그램을 만들려면 Windows 스토어 응용 프로그램.COM 구성 요소 생성에 WRL 은 ATL에 비해 적은 코드가 필요COM의 하위 집합에 대 한 내용은 하는 WRL 지원을 참조 하십시오. Windows 런타임 C++ 템플릿 라이브러리(WRL).

이 문서를 사용 하는 방법을 보여 줍니다.는 WRL 기본 COM 구성 요소를 만들 수 있습니다.가장 적합 하는 배포 메커니즘을 사용할 수 있지만이 문서에도 등록 하 고 COM 구성 요소는 데스크톱 응용 프로그램에서 사용 하는 기본적인 방법 보여 줍니다.

사용 하 여 WRL 클래식 기본 COM 구성 요소를 만들려면

  1. Visual Studio 작성 한 빈 솔루션 프로젝트입니다.예를 들어, 프로젝트의 이름을 WRLClassicCOM.

  2. 추가 된 Win32 프로젝트 솔루션입니다.예를 들어, 프로젝트의 이름을 CalculatorComponent.에 응용 프로그램 설정 탭에서 DLL.

  3. 추가 된 Midl 파일 (.idl) 파일을 프로젝트.예를 들어, 파일 이름을 CalculatorComponent.idl.

  4. 이 코드는 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. Calculatorcomponent.cpp에 정의 된 CalculatorComponent 클래스입니다.CalculatorComponent 클래스에서 상속 Microsoft::WRL::RuntimeClass.Microsoft::WRL::RuntimeClassFlags <ClassicCom> 에서 파생 되는 클래스를 지정 합니다. IUnknown 및 not IInspectable.(IInspectable 에서만 사용할 수 있습니다 스토어 응용 프로그램 구성 요소입니다.) CoCreatableClass 는 같은 함수를 사용할 수 있는 클래스에 대 한 팩터리를 만듭니다 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. Dllmain.cpp의 코드를 바꾸려면 다음 코드를 사용 합니다.이 파일에는 DLL 내보내기 함수 정의합니다.이러한 함수를 사용 하는 Microsoft::WRL::Module 클래스 모듈에 대 한 클래스 팩터리를 관리 합니다.

    #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. 추가 된 모듈 정의 파일 (.def) 파일을 프로젝트.예를 들어, 파일 이름을 CalculatorComponent.def.이 파일이 링커 내보내는 함수의 이름을 제공 합니다.

  8. 이 코드는 Calculatorcomponent.def에 추가 합니다.

    LIBRARY
    
    EXPORTS
        DllGetActivationFactory PRIVATE
        DllGetClassObject       PRIVATE
        DllCanUnloadNow         PRIVATE
    
  9. Runtimeobject.lib 링커 줄을 추가 합니다.자세한 내용은 링커 입력 파일로 사용하는 .Lib 파일.

데스크톱 응용 프로그램에서 COM 구성 요소를 사용 하려면

  1. COM 구성 요소는 Windows 레지스트리에 등록 합니다.이렇게 하려면 등록 항목 파일 만들기, 이름 RegScript.reg를 클릭 하 고 다음 텍스트를 추가 합니다.대체 < dll 경로 > DLL의 경로를-예를 들어, 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. Regscript.reg를 실행 하거나 프로젝트의 추가 빌드 후 이벤트.자세한 내용은 빌드 전 이벤트/빌드 후 이벤트 명령줄 대화 상자을 참조하십시오.

  3. 추가 된 Win32 콘솔 응용 프로그램 프로젝트를 솔루션입니다.예를 들어, 프로젝트의 이름을 계산기.

  4. 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
    */
    

강력한 프로그래밍

이 문서 표준 COM 함수를 사용 하 여 사용할 수 있는 방법을 보여 줍니다 있는 WRL COM 구성 요소를 작성 하 고 모든 COM 기반 기술을 사용할 수 있도록 합니다.또한 사용할 수 있습니다 WRL 과 같은 형식이 Microsoft::WRL::ComPtr COM 및 기타 개체의 수명을 관리 하는 데스크톱 응용 프로그램에서.다음 코드에서는 WRL 의 수명을 관리 하는 ICalculatorComponent 포인터입니다.CoInitializeWrapper 클래스는 COM 라이브러리 해제 되 고 또한 COM 라이브러리의 수명을 outlives는 것을 보장 한다는 보장은 RAII 래퍼입니다는 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;
}

참고 항목

개념

Windows 런타임 C++ 템플릿 라이브러리(WRL)