비동기 이벤트 알림 수신

비동기 이벤트 알림은 애플리케이션이 시스템 리소스를 독점하지 않고 이벤트를 지속적으로 모니터링할 수 있는 기술입니다. 비동기 이벤트 알림에는 다른 비동기 호출과 동일한 보안 제한이 있습니다. 대신 반동기 호출을 수행할 수 있습니다. 자세한 내용은 메서드 호출을 참조하세요.

클라이언트로 라우팅되는 비동기 이벤트의 큐는 매우 커질 가능성이 있습니다. 따라서 WMI는 메모리 부족이 발생하지 않도록 시스템 차원의 정책을 구현합니다. WMI는 이벤트 속도를 늦추거나 큐가 특정 크기를 초과할 때 큐에서 이벤트를 삭제하기 시작합니다.

WMI는 Win32_WMISetting 클래스의 LowThresholdOnEventsHighThresholdOnEvents 속성을 사용하여 메모리 부족 회피에 대한 제한을 설정합니다. 최소값은 WMI가 이벤트 알림 속도를 늦추기 시작해야 하는 시기를 나타내며 최대값은 이벤트 삭제를 시작할 시기를 나타냅니다. 낮은 임계값과 높은 임계값의 기본값은 각각 1000000(10MB) 및 2000000(20MB)입니다. 또한 이벤트를 삭제하기 전에 WMI가 대기해야 하는 시간을 설명하도록 MaxWaitOnEvents 속성을 설정할 수 있습니다. MaxWaitOnEvents의 기본값은 2000 또는 2초입니다.

VBScript에서 비동기 이벤트 알림 수신

이벤트 알림을 수신하기 위한 스크립팅 호출은 기본적으로 동일한 보안 문제가 있는 모든 비동기 호출과 동일합니다. 자세한 내용은 VBScript를 사용하여 비동기 호출하기를 참조하세요.

VBScript에서 비동기 이벤트 알림을 받으려면

  1. WScript.CreateObject를 호출하고 ‘WbemScripting’의 progid 및 SWbemSink의 개체 형식을 지정하여 싱크 개체를 만듭니다. 싱크 개체는 알림을 받습니다.

  2. 처리하려는 각 이벤트에 대한 서브루틴을 작성합니다. 다음 표에서는 SWbemSink 이벤트를 나열합니다.

    이벤트 의미
    OnObjectReady 개체의 반환을 싱크에 보고합니다. 이 호출을 사용하면 작업이 완료될 때까지 매번 하나의 개체를 반환합니다.
    OnCompleted 비동기 호출이 완료되면 보고합니다. 이 이벤트는 작업이 무기한인 경우 발생하지 않습니다.
    OnObjectPut 비동기 put 작업의 완료를 보고합니다. 이 이벤트는 인스턴스 또는 저장된 클래스의 개체 경로를 반환합니다.
    OnProgress 진행 중인 비동기 호출의 상태를 보고합니다. 모든 공급자가 중간 진행률 보고서를 지원하는 것은 아닙니다.
    취소 이 개체 싱크와 연결된 모든 미해결 비동기 작업을 취소합니다.

     

다음 VBScript 코드 예제에서는 10초 폴링 간격으로 프로세스 삭제를 알립니다. 이 스크립트에서 서브루틴 SINK_OnObjectReady는 이벤트 발생을 처리합니다. 예제에서 싱크 개체의 이름은 ‘Sink’이지만 이 개체의 이름을 선택한 대로 지정할 수 있습니다.

strComputer = "." 
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\CIMV2") 
Set MySink = WScript.CreateObject( _
    "WbemScripting.SWbemSink","SINK_")

objWMIservice.ExecNotificationQueryAsync MySink, _
    "SELECT * FROM __InstanceDeletionEvent" _
    & " WITHIN 10 WHERE TargetInstance ISA 'Win32_Process'"


WScript.Echo "Waiting for events..."

While (True)
    Wscript.Sleep(1000)
Wend

Sub SINK_OnObjectReady(objObject, objAsyncContext)
    Wscript.Echo "__InstanceDeletionEvent event has occurred."
End Sub

Sub SINK_OnCompleted(objObject, objAsyncContext)
    WScript.Echo "Event call complete."
End Sub

C++에서 비동기 이벤트 알림 수신

비동기 알림을 수행하려면 WMI(Windows Management Instrumentation)에서 이벤트를 모니터링하고 수신하기 위한 별도의 스레드만 만듭니다. 메시지를 수신하면 이 스레드는 주 애플리케이션에 알립니다.

별도의 스레드를 전용으로 사용하면 이벤트가 도착하기를 기다리는 동안 주 프로세스가 다른 작업을 수행할 수 있습니다. 알림을 비동기식으로 전달하면 성능이 향상되지만 필요한 수준보다 보안이 저하될 수 있습니다. C++에서는 IWbemUnsecuredApartment 인터페이스를 사용하거나 보안 설명자에 대한 액세스 검사를 수행할 수 있습니다. 자세한 내용은 비동기 호출에서 보안 설정을 참조하세요.

비동기 이벤트 알림을 설정하려면

  1. 비동기 알림을 초기화하기 전에 메모리 부족 회피 매개 변수가 Win32_WMISetting에 올바르게 설정되었는지 확인합니다.

  2. 수신하려는 이벤트의 종류를 결정합니다.

    WMI는 내부 및 외부 이벤트를 지원합니다. 내장 이벤트는 WMI에 의해 미리 정의된 이벤트인 반면, 외래 이벤트는 타사 공급자가 정의한 이벤트입니다. 자세한 내용은 수신할 이벤트 유형 결정을 참조하세요.

다음 절차에서는 C++에서 비동기 이벤트 알림을 받는 방법을 설명합니다.

C++에서 비동기 이벤트 알림을 받으려면

  1. CoInitializeExCoInitializeSecurity 함수에 대한 호출을 사용하여 애플리케이션을 설정합니다.

    CoInitializeEx를 호출하면 COM이 초기화되지만 CoInitializeSecurity는 소비자의 프로세스를 호출할 수 있는 권한을 WMI에 부여합니다. 또한 CoInitializeEx 함수는 비동기 알림에 필요한 다중 스레드 애플리케이션을 프로그래밍할 수 있는 기능도 부여합니다. 자세한 내용은 WMI 보안 유지 관리를 참조하세요.

    이 항목의 코드를 올바르게 컴파일하려면 다음 참조 및 #include 문이 필요합니다.

    #define _WIN32_DCOM
    #include <iostream>
    using namespace std;
    #include <wbemidl.h>
    

    다음 코드 예제에서는 CoInitializeExCoInitializeSecurity 호출을 사용하여 임시 이벤트 소비자를 설정하는 방법을 설명합니다.

    void main(int argc, char **argv)
    {
        HRESULT hr = 0;
        hr = CoInitializeEx (0, COINIT_MULTITHREADED);
        hr = CoInitializeSecurity (NULL, 
           -1, 
           NULL, 
           NULL,   
           RPC_C_AUTHN_LEVEL_NONE, 
           RPC_C_IMP_LEVEL_IMPERSONATE, 
           NULL,
           EOAC_NONE,
           NULL); 
    
        if (FAILED(hr))
        {
           CoUninitialize();
           cout << "Failed to initialize security. Error code = 0x"
               << hex << hr << endl;
           return;
        }
    
    // ...
    }
    
  2. IWbemObjectSink 인터페이스를 통해 싱크 개체를 만듭니다.

    WMI는 IWbemObjectSink를 사용하여 이벤트 알림을 보내고 비동기 작업 또는 이벤트 알림에 관한 상태를 보고합니다.

  3. IWbemServices::ExecNotificationQueryAsync 메서드에 대한 호출을 사용해 이벤트 소비자를 등록합니다.

    pResponseHandler 매개 변수가 이전 단계에서 만든 싱크 개체를 가리키는지 확인합니다.

    등록의 목적은 필요한 알림만 수신하는 것입니다. 불필요한 알림을 받으면 처리 및 배달 시간을 허비하게 됩니다. 및 은(는) WMI의 필터링 기능을 최대한 활용하지 않습니다.

    그러나 임시 소비자는 둘 이상의 이벤트 유형을 받을 수 있습니다. 이 경우 임시 소비자는 각 이벤트 유형에 대해 IWbemServices::ExecNotificationQueryAsync를 별도로 호출해야 합니다. 예를 들어, 소비자는 새 프로세스가 생성될 때(인스턴스 생성 이벤트 또는 __InstanceCreationEvent) 알림을 요구할 수 있으며 특정 레지스트리 키(RegistryKeyChangeEvent와 같은 레지스트리 이벤트)의 변경 내용에 대해서도 알림을 요구할 수 있습니다. 따라서 소비자는 ExecNotificationQueryAsync를 한 번 호출하여 인스턴스 생성 이벤트를 등록하고 다른 하나는 ExecNotificationQueryAsync를 호출하여 레지스트리 이벤트에 등록합니다.

    여러 이벤트에 등록하는 이벤트 소비자를 만들도록 선택하는 경우 동일한 싱크에 여러 클래스를 등록하지 않아야 합니다. 그 대신 등록된 이벤트의 각 클래스에 대해 별도의 싱크를 사용하세요. 전용 싱크가 있으면 처리를 간소화하고 유지 관리를 지원하므로 다른 등록에 영향을 미치지 않고 하나의 등록을 취소할 수 있습니다.

  4. 이벤트 소비자에서 필요한 모든 작업을 수행합니다.

    이 단계에서는 대부분의 코드를 포함해야 하며 사용자 인터페이스에 이벤트를 표시하는 등의 활동도 포함해야 합니다.

  5. 완료되면 IWbemServices::CancelAsyncCall 이벤트에 대한 호출을 사용하여 임시 이벤트 소비자의 등록을 취소합니다.

    CancelAsyncCall에 대한 호출의 성공 또는 실패 여부에 관계없이 개체 참조 수가 0에 도달할 때까지 싱크 개체를 삭제하지 마세요. 자세한 내용은 메서드 호출을 참조하세요.