예제: 공급자 메서드 호출

이 항목의 절차 및 코드 예제를 사용하여 COM 초기화를 수행하고, 로컬 컴퓨터에서 WMI에 연결하고, 공급자 메서드를 호출한 후 정리하는 완전한 WMI 클라이언트 애플리케이션을 만들 수 있습니다. Win32_Process::Create 메서드는 Notepad.exe를 새 프로세스에서 시작하는 데 사용됩니다.

다음 절차는 WMI 애플리케이션을 실행하는 데 사용됩니다. 1~5단계에서는 WMI를 설정하고 연결하며, 6단계에서는 공급자 메서드가 호출됩니다.

공급자 메서드를 호출하려면 다음을 수행합니다.

  1. CoInitializeEx를 호출하여 COM 매개 변수를 초기화합니다.

    자세한 내용은 WMI 응용 프로그램에 대한 COM 초기화를 참조하세요.

  2. CoInitializeSecurity를 호출하여 COM 프로세스 보안을 초기화합니다.

    자세한 내용은 C++를 사용하여 기본 프로세스 보안 수준 설정을 참조하세요.

  3. CoCreateInstance를 호출하여 WMI에 대한 초기 로케이터를 가져옵니다.

    자세한 내용은 WMI 네임스페이스에 대한 연결 만들기를 참조하세요.

  4. IWbemLocator::ConnectServer를 호출하여 로컬 컴퓨터에서 root\cimv2 네임스페이스의 IWbemServices에 대한 포인터를 가져옵니다. 원격 컴퓨터에 연결하려면 예: 원격 컴퓨터에서 WMI 데이터 가져오기를 참조하세요.

    자세한 내용은 WMI 네임스페이스에 대한 연결 만들기를 참조하세요.

  5. WMI 서비스가 CoSetProxyBlanket을 호출하여 클라이언트를 가장할 수 있도록 IWbemServices 프록시 보안을 설정합니다.

    자세한 내용은 WMI 연결에서 보안 수준 설정을 참조하세요.

  6. IWbemServices 포인터를 사용하여 WMI에 요청을 수행합니다. 이 예제에서는 IWbemServices::ExecMethod를 사용하여 공급자 메서드 Win32_Process::Create를 호출합니다.

    WMI에 요청을 수행하는 방법에 대한 자세한 내용은 클래스 및 인스턴스 정보 조작메서드 호출을 참조하세요.

    공급자 메서드에 입력 매개 변수 또는 출력 매개 변수가 있는 경우 해당 매개 변수의 값을 IWbemClassObject 포인터에 전달해야 합니다. 입력 매개 변수의 경우 입력 매개 변수 정의의 인스턴스를 생성한 다음 이 새 인스턴스의 값을 설정해야 합니다. Win32_Process::Create 메서드를 사용하려면 CommandLine 입력 매개 변수의 값이 올바르게 실행되어야 합니다.

    다음 코드 예제에서는 IWbemClassObject 포인터를 만들고 Win32_Process::Create 입력 매개 변수 정의의 새 인스턴스를 생성한 다음 CommandLine 입력 매개 변수의 값을 Notepad.exe로 설정합니다.

    // Set up to call the Win32_Process::Create method
    BSTR MethodName = SysAllocString(L"Create");
    BSTR ClassName = SysAllocString(L"Win32_Process");
    
    IWbemClassObject* pClass = NULL;
    hres = pSvc->GetObject(ClassName, 0, NULL, &pClass, NULL);
    
    IWbemClassObject* pInParamsDefinition = NULL;
    hres = pClass->GetMethod(MethodName, 0, 
        &pInParamsDefinition, NULL);
    
    IWbemClassObject* pClassInstance = NULL;
    hres = pInParamsDefinition->SpawnInstance(0, &pClassInstance);
    
    // Create the values for the in-parameters
    VARIANT varCommand;
    varCommand.vt = VT_BSTR;
    varCommand.bstrVal = _bstr_t(L"notepad.exe");
    
    // Store the value for the in-parameters
    hres = pClassInstance->Put(L"CommandLine", 0,
        &varCommand, 0);
    wprintf(L"The command is: %s\n", V_BSTR(&varCommand));
    

    다음 코드 예제에서는 Win32_Process::Create 메서드의 출력 매개 변수가 IWbemClassObject 포인터에 전달되는 방법을 보여 줍니다. 출력 매개 변수 값은 IWbemClassObject::Get 메서드로 획득되어 사용자에게 표시될 수 있도록 VARIANT 변수에 저장됩니다.

    // Execute Method
    IWbemClassObject* pOutParams = NULL;
    hres = pSvc->ExecMethod(ClassName, MethodName, 0,
        NULL, pClassInstance, &pOutParams, NULL);
    
    VARIANT varReturnValue;
    hres = pOutParams->Get(_bstr_t(L"ReturnValue"), 0, 
        &varReturnValue, NULL, 0);
    

다음 코드 예제에서는 WMI를 사용하여 공급자 메서드를 호출하는 방법을 보여 줍니다.

#define _WIN32_DCOM

#include <iostream>
using namespace std;
#include <comdef.h>
#include <Wbemidl.h>

#pragma comment(lib, "wbemuuid.lib")

int main(int iArgCnt, char ** argv)
{
    HRESULT hres;

    // Step 1: --------------------------------------------------
    // Initialize COM. ------------------------------------------

    hres =  CoInitializeEx(0, COINIT_MULTITHREADED); 
    if (FAILED(hres))
    {
        cout << "Failed to initialize COM library. Error code = 0x" 
             << hex << hres << endl;
        return 1;                  // Program has failed.
    }

    // Step 2: --------------------------------------------------
    // Set general COM security levels --------------------------

    hres =  CoInitializeSecurity(
        NULL, 
        -1,                          // COM negotiates service
        NULL,                        // Authentication services
        NULL,                        // Reserved
        RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication 
        RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation
        NULL,                        // Authentication info
        EOAC_NONE,                   // Additional capabilities 
        NULL                         // Reserved
        );


    if (FAILED(hres))
    {
        cout << "Failed to initialize security. Error code = 0x" 
             << hex << hres << endl;
        CoUninitialize();
        return 1;                      // Program has failed.
    }

    // Step 3: ---------------------------------------------------
    // Obtain the initial locator to WMI -------------------------

    IWbemLocator *pLoc = NULL;

    hres = CoCreateInstance(
        CLSID_WbemLocator,
        0, 
        CLSCTX_INPROC_SERVER, 
        IID_IWbemLocator, (LPVOID *) &pLoc);
 
    if (FAILED(hres))
    {
        cout << "Failed to create IWbemLocator object. "
             << "Err code = 0x"
             << hex << hres << endl;
        CoUninitialize();
        return 1;                 // Program has failed.
    }

    // Step 4: ---------------------------------------------------
    // Connect to WMI through the IWbemLocator::ConnectServer method

    IWbemServices *pSvc = NULL;
 
    // Connect to the local root\cimv2 namespace
    // and obtain pointer pSvc to make IWbemServices calls.
    hres = pLoc->ConnectServer(
        _bstr_t(L"ROOT\\CIMV2"), 
        NULL,
        NULL, 
        0, 
        NULL, 
        0, 
        0, 
        &pSvc
    );

    if (FAILED(hres))
    {
        cout << "Could not connect. Error code = 0x" 
             << hex << hres << endl;
        pLoc->Release();
        CoUninitialize();
        return 1;                // Program has failed.
    }

    cout << "Connected to ROOT\\CIMV2 WMI namespace" << endl;


    // Step 5: --------------------------------------------------
    // Set security levels for the proxy ------------------------

    hres = CoSetProxyBlanket(
        pSvc,                        // Indicates the proxy to set
        RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx 
        RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx 
        NULL,                        // Server principal name 
        RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx 
        RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
        NULL,                        // client identity
        EOAC_NONE                    // proxy capabilities 
    );

    if (FAILED(hres))
    {
        cout << "Could not set proxy blanket. Error code = 0x" 
             << hex << hres << endl;
        pSvc->Release();
        pLoc->Release();
        CoUninitialize();
        return 1;               // Program has failed.
    }

    // Step 6: --------------------------------------------------
    // Use the IWbemServices pointer to make requests of WMI ----

    // set up to call the Win32_Process::Create method
    BSTR MethodName = SysAllocString(L"Create");
    BSTR ClassName = SysAllocString(L"Win32_Process");

    IWbemClassObject* pClass = NULL;
    hres = pSvc->GetObject(ClassName, 0, NULL, &pClass, NULL);

    IWbemClassObject* pInParamsDefinition = NULL;
    hres = pClass->GetMethod(MethodName, 0, 
        &pInParamsDefinition, NULL);

    IWbemClassObject* pClassInstance = NULL;
    hres = pInParamsDefinition->SpawnInstance(0, &pClassInstance);

    // Create the values for the in parameters
    VARIANT varCommand;
    varCommand.vt = VT_BSTR;
    varCommand.bstrVal = _bstr_t(L"notepad.exe");

    // Store the value for the in parameters
    hres = pClassInstance->Put(L"CommandLine", 0,
        &varCommand, 0);
    wprintf(L"The command is: %s\n", V_BSTR(&varCommand));

    // Execute Method
    IWbemClassObject* pOutParams = NULL;
    hres = pSvc->ExecMethod(ClassName, MethodName, 0,
    NULL, pClassInstance, &pOutParams, NULL);

    if (FAILED(hres))
    {
        cout << "Could not execute method. Error code = 0x" 
             << hex << hres << endl;
        VariantClear(&varCommand);
        SysFreeString(ClassName);
        SysFreeString(MethodName);
        pClass->Release();
        pClassInstance->Release();
        pInParamsDefinition->Release();
        pOutParams->Release();
        pSvc->Release();
        pLoc->Release();
        CoUninitialize();
        return 1;               // Program has failed.
    }

    // To see what the method returned,
    // use the following code.  The return value will
    // be in &varReturnValue
    VARIANT varReturnValue;
    hres = pOutParams->Get(_bstr_t(L"ReturnValue"), 0, 
        &varReturnValue, NULL, 0);


    // Clean up
    //--------------------------
    VariantClear(&varCommand);
    VariantClear(&varReturnValue);
    SysFreeString(ClassName);
    SysFreeString(MethodName);
    pClass->Release();
    pClassInstance->Release();
    pInParamsDefinition->Release();
    pOutParams->Release();
    pLoc->Release();
    pSvc->Release();
    CoUninitialize();
    return 0;
}