C++를 사용하여 비동기적 호출 만들기

C++로 작성된 WMI 응용 프로그램은 IWbemServices COM 인터페이스의 여러 메서드를 사용하여 비동기적 호출을 수행할 수 있습니다. 그러나 반동기적 호출이 비동기적 호출보다 더 안전하기 때문에 WMI 메서드 또는 공급자 메서드를 호출하는 데 권장되는 절차는 반동기적 호출을 사용하는 것입니다. 자세한 내용은 C++를 사용하여 반동기적 호출 만들기비동기적 호출에서 보안 설정을 참조하세요.

다음 절차에서는 프로세스에서 싱크를 사용하여 비동기적 호출을 하는 방법을 설명합니다.

C++를 사용하여 비동기적 호출하기

  1. IWbemObjectSink 인터페이스를 구현합니다.

    비동기적 호출을 하는 모든 응용 프로그램은 IWbemObjectSink를 구현해야 합니다. 또한 임시 이벤트 소비자는 IWbemObjectSink를 구현하여 이벤트 알림을 받습니다.

  2. 대상 WMI 네임스페이스에 로그온합니다.

    응용 프로그램은 초기화 단계에서 항상 COM 함수 CoInitializeSecurity를 호출해야 합니다. 비동기적 호출을 하기 전에 하지 않으면 WMI는 비동기적 호출을 완료하지 않고 응용 프로그램 싱크를 해제합니다. 자세한 내용은 WMI 응용 프로그램에 대한 COM 초기화를 참조하세요.

  3. 싱크에 대한 보안을 설정합니다.

    비동기적 호출은 응용 프로그램에 대한 WMI 액세스를 허용하는 등 처리해야 할 수 있는 다양한 보안 문제를 만듭니다. 자세한 내용은 비동기적 호출에서 보안 설정을 참조하세요.

  4. 비동기적 호출을 합니다.

    메서드는 WBEM_S_NO_ERROR 성공 코드와 함께 즉시 반환됩니다. 응용 프로그램은 작업이 완료될 때까지 기다리는 동안 다른 작업을 진행할 수 있습니다. WMI는 응용 프로그램의 IWbemObjectSink 구현에서 메서드를 호출하여 응용 프로그램에 다시 보고합니다.

  5. 필요한 경우 주기적으로 구현에서 업데이트를 확인합니다.

    응용 프로그램은 WBEM_FLAG_SEND_STATUS에 대한 비동기적 호출에서 lFlags 매개 변수를 설정하여 중간 상태 알림을 받을 수 있습니다. WMI는 IWbemObjectSinklFlags 매개 변수를 WBEM_STATUS_PROGRESS에 설정하여 호출 상태를 보고합니다.

  6. 필요한 경우 IWbemServices::CancelCallAsync 메서드를 호출해 WMI가 처리를 완료하기 전에 호출을 취소할 수 있습니다.

    CancelAsyncCall 메서드는 IWbemObjectSink 인터페이스에 대한 포인터를 즉시 해제하여 비동기적 처리를 취소하고 CancelAsyncCall이 반환되기 전에 포인터가 해제되도록 보장합니다.

    IUnsecured 인터페이스를 구현하는 래퍼 개체를 사용해 IWbemObjectSink를 호스트하는 경우 몇 가지 추가 문제가 발생할 수 있습니다. 응용 프로그램은 원래 비동기적 호출에서 전달된 CancelAsyncCall에 동일한 포인터를 전달해야 하므로 취소가 필요하지 않다는 것이 분명해질 때까지 응용 프로그램이 래퍼 개체를 유지해야 합니다. 자세한 내용은 비동기적 호출에서 보안 설정을 참조하세요.

  7. 완료되면 포인터를 정리하고 응용 프로그램을 종료합니다.

    WMI는 SetStatus 메서드를 통해 최종 상태 호출을 제공합니다.

    참고

    최종 상태 업데이트를 보낸 후 WMI는 IWbemObjectSink 인터페이스를 구현하는 클래스에 대해 Release 메서드를 호출하여 개체 싱크를 해제합니다. 이전 예제에서는 QuerySink::Release 메서드입니다. 싱크 개체의 수명을 제어하려는 경우 초기 참조 수가 1인 싱크를 구현할 수 있습니다.

     

    클라이언트 응용 프로그램이 두 개의 겹치는 비동기적 호출에서 동일한 싱크 인터페이스를 전달하는 경우 WMI는 콜백의 순서를 보장하지 않습니다. 겹치는 비동기적 호출을 수행한 클라이언트 응용 프로그램이 서로 다른 싱크 개체를 전달하거나 호출을 직렬화해야 합니다.

이전 코드 예제에는 다음 참조 및 #include 문이 필요합니다.

#include <iostream>
using namespace std;
#pragma comment(lib, "wbemuuid.lib")
#include <wbemidl.h>

다음 예제에서는 ExecQueryAsync 메서드를 사용하여 비동기적 쿼리를 만드는 방법을 설명하지만 보안 설정을 만들거나 IWbemObjectSink 개체를 해제하지는 않습니다. 자세한 내용은 비동기적 호출에서 보안 설정을 참조하세요.

// Set input parameters to ExecQueryAsync.
BSTR QueryLang = SysAllocString(L"WQL");
BSTR Query = SysAllocString(L"SELECT * FROM MyClass");

// Create IWbemObjectSink object and set pointer.
QuerySink *pSink = new QuerySink;

IWbemServices* pSvc = 0;

// Call ExecQueryAsync.
HRESULT hRes = pSvc->ExecQueryAsync(QueryLang, 
                                    Query, 
                                    0, 
                                    NULL, 
                                    pSink);

// Check for errors.
if (hRes)
{
    printf("ExecQueryAsync failed with = 0x%X\n", hRes);
    SysFreeString(QueryLang);
    SysFreeString(Query);
    delete pSink;    
    return ERROR;
}

참고

QuerySink 클래스가 정의되지 않았기 때문에 위의 코드는 오류 없이 컴파일되지 않습니다. QuerySink에 대한 자세한 내용은 IWbemObjectSink를 참조하세요.

 

메서드 호출