WMI イベントの受信

WMI には、WMI データとサービスの変更に関する通知を生成するイベント インフラストラクチャが含まれています。 WMI "イベント クラス" は、特定のイベントが発生したときに通知を提供します。

このトピックでは、以下のセクションについて説明します。

イベント クエリ

半同期または非同期クエリを作成して、イベント ログ、プロセスの作成、サービスの状態、コンピューターの可用性またはディスク ドライブの空き領域、その他のエンティティやイベントに対する変更を監視できます。 スクリプトでは、SWbemServices.ExecNotificationQuery メソッドを使用してイベントをサブスクライブします。 C++ では、IWbemServices::ExecNotificationQuery が使用されます。 詳細については、「メソッドの呼び出し」を参照してください。

標準 WMI データ モデルの変更の通知は、"組み込みイベント" と呼ばれます。 __InstanceCreationEvent または __NamespaceDeletionEvent は、組み込みイベントの例です。 プロバイダー イベントを定義するためにプロバイダーが行った変更の通知は、"外因性イベント" と呼ばれます。 たとえば、システム レジストリ プロバイダー電源管理イベント プロバイダーWin32 プロバイダーは、独自のイベントを定義します。 詳細については、「受信するイベントの種類の決定」を参照してください。

次のスクリプト コード例は、イベント クラス Win32_NTLogEvent の組み込み __InstanceCreationEvent のクエリです。 このプログラムはバックグラウンドで実行でき、イベントが発生するとメッセージが表示されます。 [Waiting for events] (イベントの待機中) ダイアログ ボックスを閉じると、プログラムはイベントの待機を停止します。 SeSecurityPrivilege を有効にする必要があることに注意してください。

Sub SINK_OnObjectReady(objObject, objAsyncContext)
    WScript.Echo (objObject.TargetInstance.Message)
End Sub

Set objWMIServices = GetObject( _
    "WinMgmts:{impersonationLevel=impersonate, (security)}") 

' Create the event sink object that receives the events
Set sink = WScript.CreateObject("WbemScripting.SWbemSink","SINK_")
 
' Set up the event selection. SINK_OnObjectReady is called when
' a Win32_NTLogEvent event occurs
objWMIServices.ExecNotificationQueryAsync sink,"SELECT * FROM __InstanceCreationEvent " & "WHERE TargetInstance ISA 'Win32_NTLogEvent' "

WScript.Echo "Waiting for events"

# Define event Query
$query = "SELECT * FROM __InstanceCreationEvent 
          WHERE TargetInstance ISA 'Win32_NTLogEvent' "

<# Register for event - also specify an action that
displays the log event when the event fires.#>

Register-WmiEvent -Source Demo1 -Query $query -Action {
                Write-Host "Log Event occured"
                $global:myevent = $event
                Write-Host "EVENT MESSAGE"
                Write-Host $event.SourceEventArgs.NewEvent.TargetInstance.Message}
<# So wait #>
"Waiting for events"

次の VBScript コード例は、レジストリ プロバイダーが定義する外因性イベント __RegistryValueChangeEvent を示しています。 スクリプトは、SWbemServices.ExecNotificationQueryAsync の呼び出しを使用して一時コンシューマーを作成し、スクリプトの実行中にのみイベントを受信します。 次のスクリプトは、コンピューターが再起動されるか、WMI が停止されるか、スクリプトが停止されるまで無期限に実行されます。 スクリプトを手動で停止するには、タスク マネージャーを使用してプロセスを停止します。 プログラムで停止するには、Win32_Process クラスの Terminate メソッドを使用します。 詳細については、「非同期呼び出しでのセキュリティの設定」を参照してください。

strComputer = "."

Set objWMIServices=GetObject( _
    "winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\default")

set objSink = WScript.CreateObject("WbemScripting.SWbemSink","SINK_")


objWMIServices.ExecNotificationQueryAsync objSink, _
    "Select * from RegistryValueChangeEvent Where Hive = 'HKEY_LOCAL_MACHINE' and KeyPath = 'SYSTEM\\ControlSet001\\Control' and ValueName = 'CurrentUser'"

WScript.Echo "Waiting for events..."

While (True) 
     WScript.Sleep (1000)
Wend

 
WScript.Echo "Listening for Registry Change Events..." & vbCrLf 

While(True) 
    WScript.Sleep 1000 
Wend 

Sub SINK_OnObjectReady(wmiObject, wmiAsyncContext) 
    WScript.Echo "Received Registry Value Change Event" & vbCrLf & wmiObject.GetObjectText_() 
End Sub

イベント コンシューマー

スクリプトまたはアプリケーションの実行中に、次のコンシューマーを使用してイベントを監視または使用できます。

  • 一時イベント コンシューマー

    "一時コンシューマー" は、WMI イベントを受信する WMI クライアント アプリケーションです。 WMI には、クライアント アプリケーションに送信する WMI のイベントを指定するために使用する一意のインターフェイスが含まれています。 一時イベント コンシューマーは、ユーザーが明示的に読み込んだときにのみ機能するため、一時的と見なされます。 詳細については、「アプリケーションの期間中のイベントの受信」を参照してください。

  • 永続イベント コンシューマー

    "永続コンシューマー" は、常に WMI イベントを受信できる COM オブジェクトです。 永続イベント コンシューマーは、一連の永続的なオブジェクトとフィルターを使用して WMI イベントを取り込みます。 一時イベント コンシューマーと同様に、WMI イベントを取り込む一連の WMI オブジェクトとフィルターを設定します。 フィルターに一致するイベントが発生すると、WMI は永続イベント コンシューマーを読み込み、イベントについて通知します。 永続コンシューマーは WMI リポジトリに実装されており、WMI に登録されている実行可能ファイルであるため、永続イベント コンシューマーは、作成後、および WMI が実行されている限りオペレーティング システムの再起動後もイベントを操作および受信します。 詳細については、「常にイベントを受信する」を参照してください。

イベントを受信するスクリプトまたはアプリケーションには、セキュリティに関する特別な考慮事項があります。 詳細については、「WMI イベントのセキュリティ保護」を参照してください。

アプリケーションまたはスクリプトでは、標準のコンシューマー クラスを提供する組み込みの WMI イベント プロバイダーを使用できます。 各標準コンシューマー クラスは、電子メール メッセージを送信するかスクリプトを実行することで、異なるアクションでイベントに応答します。 標準コンシューマー クラスを使用して永続イベント コンシューマーを作成するためにプロバイダー コードを記述する必要はありません。 詳細については、「標準コンシューマーを使用したイベントの監視と対応」を参照してください。

イベントの提供

イベント プロバイダーは、WMI にイベントを送信する COM コンポーネントです。 イベント プロバイダーを作成して、C++ または C# アプリケーションでイベントを送信できます。 ほとんどのイベント プロバイダーは、WMI のオブジェクト (アプリケーションやハードウェア項目など) を管理します。 詳細については、「イベント プロバイダーの作成」を参照してください。

時間指定または繰り返しイベントは、所定の時間に発生するイベントです。

WMI には、アプリケーションの時間指定または繰り返しイベントを作成する次の方法が用意されています。

  • 標準の Microsoft イベント インフラストラクチャ。
  • 特殊なタイマー クラス。

詳細については、「時間指定または繰り返しイベントの受信」を参照してください。 イベント プロバイダーを作成するときは、「イベントを安全に提供する」で識別されるセキュリティ情報を考慮してください。

永続イベント サブスクリプションを \root\subscription 名前空間にコンパイルすることをお勧めします。 詳細については、「名前空間をまたがる永続イベント サブスクリプションの実装」を参照してください。

サブスクリプションのクォータ

イベントのポーリングにより、巨大なデータ セットに対するクエリをサポートするプロバイダーのパフォーマンスが低下するおそれがあります。 さらに、動的プロバイダーを持つ名前空間への読み取りアクセス権を持つユーザーは、サービス拒否 (DoS) 攻撃を実行できます。 WMI は、結合されたすべてのユーザーと、\root 名前空間にある __ArbitratorConfiguration の単一インスタンス内の各イベント コンシューマーに対してクォータを保持します。 これらのクォータは、各名前空間ではなくグローバルです。 クォータを変更することはできません。

WMI は現在、__ArbitratorConfiguration のプロパティを使用してクォータを適用しています。 各クォータには、ユーザーごと、およびすべてのユーザーを組み合わせた合計のバージョンがあり、名前空間ごとはありません。 次の表に、__ArbitratorConfiguration プロパティに適用されるクォータの一覧を示します。

Total/PerUser Quota
TemporarySubscriptionsTotal
TemporarySubscriptionsPerUser
10,000
1,000
PermanentSubscriptionsTotal
PermanentSubscriptionsPerUser
10,000
1,000
PollingInstructionsTotal
PollingInstructionsPerUser
10,000
1,000
PollingMemoryTotal
PollingMemoryPerUser
10,000,000 (0x989680) バイト
5,000,000 (0x4CB40) バイト

名前空間に FULL_WRITE アクセス許可を持つ管理者またはユーザーは、__ArbitratorConfiguration のシングルトン インスタンスを変更できます。 WMI は、ユーザーごとのクォータを追跡します。

WMI の使用