IV 이벤트 통지 질의들
지금까지 WMI는 관리 대상 객체를 표시하여 단순 데이터 검사를 위한 도구였습니다.
하지만 이를 이용하면 더 많은 것을 할 수 있습니다. 또 WMI를 사용하면 특정 이벤트가 트리거되는 경우 응용 프로그램에 알림을 보낼 수 있습니다. 이러한 알림 요청은 이벤트 알림 쿼리를 작성하여 수행됩니다.
이 특수 유형의 쿼리는 두 가지 방식에서 이전에 본 것과 다릅니다:
첫째, 이벤트 알림 쿼리는 비동기식 또는 반동기식으로 만들 수 있지만 동기식으로 만들 수는 없습니다. 둘째, 이벤트 소비자의 프로그래밍 모델이 약간 다릅니다.
영구 및 임시 이벤트 소비자들
WMI에서 이벤트 알림을 받는 중심에 있는 응용 프로그램을 이벤트 소비자라고 합니다. 이벤트 소비자는 영구 이벤트 소비자와 임시 이벤트 소비자 두 가지 유형이 있습니다. 임시 이벤트 소비자는 일정 기간 동안 이벤트 알림을 원하는 애플리케이션입니다.
일반적으로 응용 프로그램의 수명 제한 시간이 끝나면, 응용 프로그램은 WMI에서 해당 쿼리를 등록 취소합니다.
반대로 영구 이벤트 소비자는 애플리케이션이 완료 된 후에도 활성 상태를 유지할 것입니다.
Windows XP에는 몇 가지 영구 이벤트 소비자가 미리 설치되어 있으며 예를 들어 명령줄 스크립트 실행에 이벤트를 연결할 수 있습니다. 이렇게 미리 설치된 소비자를 표준 이벤트 소비자라고 합니다.
두 종류의 이벤트 소비자는 프로그래밍 관점에서 크게 다르지 않으므로 이 문서의 나머지 부분에서는 영구 이벤트 소비자를 다루지는 않겠습니다.
WMI에 등록하여 이벤트 알림을 받으려면 이벤트 소비자가 WQL 문의 형식으로 준비된 질의문이 있어야 합니다.WQL 질의문 내에서 이벤트 유형은 FROM 절로 지정됩니다. 평소와 같이 base 클래스를 사용하여 여러 유형을 지정할 수 있습니다. 하지만 유효한 쿼리를 구성하려면 지정된 클래스가 __Event 클래스에서 파생되어야 합니다. MSDN에 사용 가능한((base)) 클래스들이 나열되어 있습니다. WMI 데이터 모델의 변경과 관련된 이벤트를 고유 이벤트라고 합니다.
특히 고유 이벤트는 WMI 자체에서 생성됩니다; 제공자가 없어도 됩니다. 고유 이벤트는 클래스, 인스턴스 및 네임스페이스의 생성, 수정 및 삭제와 더 많은 관리자 특성으로 제한됩니다.
WMI 데이터 모델 외부의 변경 사항을 반영하는 이벤트를 외부 이벤트라고 하며 __ExtrinsicEvent에서 파생되어야 합니다. 여기서 이 이벤트를 언급하는 것은 문서의 완전성을 위해서 입니다.
이벤트에 대한 WQL 질의(Project DiskChange)
위에서 설명한 것처럼 소비자는 이벤트 알림을 요청하기 위해 FROM 절에 지정된 이벤트 클래스로 WQL 쿼리를 수행합니다. 이전에 본 쿼리에 추가 사항으로 FROM 절 뒤에는 필수 WITHIN 절이 옵니다.이 절은 시간 간격을 초 단위로 지정하여 WMI에 열거형에 결과를 얼마나 자주 업데이트할지 알려줍니다.
이것이 이전 섹션에서 본 쿼리 유형과의 주요 차이점입니다 - WMI는 중지하라는 지시를 받을 때까지 소비자에게 이벤트 알림을 계속 보냅니다(쿼리 호출에 전달된 열거형 또는 sink를 통해서).
이는 열거형에서 Release를 호출하거나 비동기식 경우 sink 객체에 대해 IWbemServices::CancelAsyncCall을 호출하여 수행됩니다.
소수의 고유 이벤트만 있으며 클래스 또는 인스턴스의 생성, 수정 및 삭제와 같은 보다 일반적인 특성을 가집니다. 따라서 이들은 관련 정보를 직접 전달하지 않습니다. 대신 이것들은 실제 데이터를 참조하는 속성을 가지고 있습니다.
예를 들어 인스턴스 작업을 참조하는 이벤트 클래스는 관련 인스턴스를 지정하는 __InstanceOperationEvent에서 상속되는 TargetInstance 속성이 포함하고 있습니다.
이 속성은 ISA 연산자를 사용하여 관심 클래스에 대해 WHERE 절에서 확인됩니다.
논리 디스크 드라이브(플로피, CD/DVD 드라이브 또는 하드 디스크)에 대한 변경 사항은 TargetInstance 값으로 Win32_LogicalDisk 인스턴스가 있는 __InstanceModificationEvents로 표시됩니다.
따라서 이러한 변경 사항에 대한 이벤트 알림 요청은 다음 WQL 문으로 수행할 수 있습니다:
SELECT * FROM __InstanceModificationEvent WITHIN 10
WHERE TargetInstance ISA 'Win32_LogicalDisk'
여기에서 WMI는 사용 가능한 모든 Win32_LogicalDisk 인스턴스의 새로운 수정 사항을 10초마다 확인하여 해당 정보에 따라 이벤트 소비자에게 알립니다.
예를 들어 이러한 이벤트는 드라이브에 CD 또는 DVD를 삽입하는 것으로 시작 됩니다.
물론 이러한 다소 일반적인 알림 요청은 특별한 인스턴스로 제한하여 보다 이벤트 특정으로 만들 수 있습니다: 이 쿼리는 결과를 논리 드라이브 'G:'로 제한합니다.
SELECT * FROM __InstanceModificationEvent WITHIN 10
WHERE ( TargetInstance ISA 'Win32_LogicalDisk' )
AND ( TargetInstance.Name = "G:" )
이벤트 알림 쿼리는 IWbemServices::ExecQuery를 호출하는 것이 아니라 IWbemServices::ExecNotificationQuery 또는 IWbemServices::ExecNotificationQueryAsync를 호출하여 비동기식으로 만듭니다.
두 경우 모두 매개 변수는 ExecNotificationQuery 플래그 인 WBEM_FLAG_RETURN_IMMEDIATELY 및 WBEM_FLAG_FORWARD_ONLY를 지정해야 한다는 추가 제약 조건 외에는 일반적인 질의와 동일합니다.
그렇지 않으면 호출이 실패합니다. 따라서 IEnumWbemClassObject::Reset을 호출해도 이러한 열거형에는 영향을 미치지 않습니다.
결과 이벤트 검색은 이전의 반동기식 쿼리와 동일하게 수행됩니다(이벤트 알림 쿼리는 적어도 반동기식입니다!).
또한 열거형에서 Release가 호출되지 않는 한 추가 이벤트를 받을 수 있습니다.
맺음말
이 문서에서는 WMI 소비자의 관점의 내용을 집중적으로 다루었습니다. 하지만 많은 부분에 대해서 언급하지 않았으며, 특히 관리 대상 객체와의 보다 직접적인 상호 작용 측면은 거의 다루지 않았습니다. 파일 시스템 또는 디렉터리 관리 구조를 순회하고 이를 사용하여 예를 들어 파일을 복사하는 방법이 그 예입니다.
WMI는 미리 정의된 데이터 구조에 대한 액세스를 허용할 뿐만 아니라 기존 데이터 구조를 확장하고 새 데이터 구조를 정의하는 메타 데이터 기능도 제공합니다.
이 모든 것은 WMI 공급자의 반대 역할과 밀접하게 연결되어 있으며 아마도 WMI 공급자 측면을 다루는 다른 문서가 적절할 것입니다.
주의 사항
항상 그렇듯이 겉보기에 훌륭해 보이는 시스템도 자세히 살펴보면 단점이 있습니다. 이는 WMI에도 적용되며 실제로 몇 가지 심각한 문제를 야기할 수 있습니다.
방화벽과 RPC
DCOM 응용 프로그램이므로 WMI 및 WMI 소비자는 객체에 원격으로 액세스할 때 RPC 서비스를 사용합니다. 요즘에는 이것이 거의 확실하게 방화벽 환경구성으로 문제가 발생 합니다.
일반적으로 TCP 포트 135 및 445는 DCOM에 의해 동적으로 할당된 포트와 함께 방화벽의 차단 목록에서 제외되어야 할 것입니다. 이 포트 수를 최소화하는 것은 상당히 까다로울 수 있습니다.
이기종으로 관리되는 대규모 회사 네트워크의 서브넷을 통과할 때 관리자가 TCP 135 및 445 포트 열어주지 않는다면 이는 중단 될 것입니다.
모든 이벤트 알림 요청을 제거하는 것을 잊지 마십시오.
이벤트 알림 쿼리를 만들 때 이러한 질의들로 생성된 모든 IEnumWbemClassObject 인스턴스들에 대해서 IUnknown::Release를 호출해야 합니다.
예를 들어 CTRL-C를 통해 비정상적으로 프로그램을 종료하여 이 작업을 수행하지 않으면 WMI는 이러한 쿼리를 계속 처리하고 더 이상 결과를 반환하지 않지만 놀랍도록 빠르고 효율적인 방식으로 CPU를 독차지 할 것입니다.
기술 자료의 KB327542도 참조하십시오.
WMI 쿼리에 상당한 시간이 소요될 수 있음
일부 유형의 쿼리는 완료하는 데 상당한 시간이 걸릴 수 있습니다.
예를 들어 이벤트 알림 쿼리는 짧은 폴링 간격이 지정된 경우에도 첫 번째 이벤트를 전달하기 전에 몇 초가 걸릴 수 있습니다. 응용 프로그램을 설계할 때 이 문제를 해결해야 합니다.
비동기 질의 및 OLE
비동기 쿼리는 아파트 스레드의 스레드들, 즉 COINIT_APARTMENTTHREADED로 CoInitializeEx를 호출하는 스레드에 의해 시작하는 것을 지양해야 할 것 같습니다. ExecQueryAsync가 WBEM_S_NO_ERROR를 반환하지만 sink가 호출되지 않는 증상이 나타납니다. 이에 대한 직관적인 해결 방법은 COINIT_MULTITHREADED를 대신 사용하거나 반동기 쿼리를 만드는 것일 겁니다.
그러나 애플리케이션이 단일 스레드 아파트에서 실행되어야 하기 때문에 때때로 COINIT_MULTITHREADED를 사용할 수 없습니다. 예를 들어 OLE 클라이언트들 같은 경우들 말입니다. 이 상황에 대한 해결책은 모든 WMI 소비자 항목을 자체 스레드로 분리하고 이를 할당 가능한 멀티스레딩 중 하나로 초기화하는 것입니다.
라이선스
이 기사에는 명시적인 라이센스가 첨부되어 있지 않지만 기사 텍스트 또는 다운로드 파일 자체에 사용 조건이 포함될 수 있습니다.
의심스러운 경우 아래 토론 게시판을 통해 작성자에게 문의하십시오.
작성자가 사용할 수 있는 라이선스 목록은 여기에서 찾을 수 있습니다.
'프로그래밍' 카테고리의 다른 글
SQL 문장 들여쓰기 (0) | 2023.02.17 |
---|---|
[JavaScript] console.log() 함수에 여러변수를 한줄로 ? (0) | 2023.02.15 |
[C++]WMI 질의 만들기-2 (0) | 2023.02.13 |
[C++]WMI 질의 만들기 - 1 (0) | 2023.02.12 |
WMI C++ 응용프로그램 예제들 (0) | 2023.02.11 |