Hey, Scripting Guy!

Hey, Scripting Guy!

TechNet コラムへようこそ。このコラムでは、よく寄せられるシステム管理スクリプトに関する質問に Scripting Guys がお答えします。システム管理スクリプトについて質問がある場合は、scripter@microsoft.com (英語のみ) までお送りください。すべての質問に回答することはできないかもしれませんが、可能な限り対応いたします。

Hey, Scripting Guy! アーカイブも忘れずにチェックしてください。

今日の質問 : 特定のプリンタで出力が行われるたびに通知を受け取る方法はありますか


特定のプリンタで出力が行われるたびに通知を受け取る方法はありますか

Q

Scripting Guy さん、よろしくお願いします。特定のプリンタで出力が行われるたびに通知を受け取る方法はありますか。

-- IL

A

IL さん、こんにちは。Scripting Guy の 1 人がかつてある会社で夏季アルバイトを体験したことがありましたが、そこは、ビル管理スタッフ室にそこそこのプリンタが 1 台あるだけの会社でした。 過去のつらい経験からこれだけは確かです。このようなプリンタで出力するたびに通知を受け取るのにさほどの労力は必要ありません。

もちろん、叫んだりわめいたりして通知することもできますが、さいわい、もっと平和的かつ文化的な方法で特定のプリンタへの出力を知らせる通知を受け取ることができます。ここでは、次のような WMI イベント通知スクリプトを使用します。

strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")

Set colPrintJobs = objWMIService. _ 
    ExecNotificationQuery("Select * From __InstanceCreationEvent " _ 
        & "Within 10 Where TargetInstance ISA 'Win32_PrintJob'")

Do While True
    Set objPrintJob = colPrintJobs.NextEvent
    If InStr(objPrintJob.TargetInstance.Name, "atl-color-printer-1") Then 
        Wscript.Echo objPrintJob.TargetInstance.Document, Now
    End If
Loop 

穏やかな方法で通知を受け取るには、まず、ローカル コンピュータ上の WMI サービスに接続します。このスクリプトは、リモート コンピュータの名前を変数 strComputer に割り当てるだけで、リモート コンピュータ上の WMI サービスに接続するように簡単に変更できます。また、プリント サーバーに接続する必要はありません。このスクリプトは、監視するプリンタ (この場合は atl-color-printer という名前のプリンタ) に接続するコンピュータで動作します。

WMI サービスに接続したら、次のコード行を実行します。

Set colPrintJobs = objWMIService. _ 
    ExecNotificationQuery("Select * From __InstanceCreationEvent " _ 
        & "Within 10 Where TargetInstance ISA 'Win32_PrintJob'")

上記のコードは、実際のイベント通知クエリです。このイベント通知クエリでは、Win32_PrintJob クラスの新しいインスタンスが作成されるたびに通知するように WMI に指示します。なぜでしょう。だれかが新しいドキュメントを印刷するたびに Win32_Print Job クラスの新しいインスタンスが生成されます。つまり、WIN32_PrintJob の新しいインスタンスが生成されるたびに通知を受け取れば、ドキュメントが印刷されたことを知ることができます。

注 : この場合の Within 10 は、10 秒ごとに新しい印刷ジョブがないかどうかをチェックすることを意味します。印刷ジョブが発生していなければ、スクリプトは一時的に休止状態になり、10 秒後に再び起動して印刷ジョブが発生していないかどうかをチェックします。Within 10、TargetInstance、ISA などの意味が不明な部分があったら、Scripting Guys の WMI イベントに関する Scripting Week 2 Web キャスト (英語) をご覧ください。

ここで 1 つ、はっきりさせようと思います。イベント通知クエリがあれば、ドキュメントが印刷されるたびにスクリプトが知らせてくれますが、それで本当に知ったことになりますか。どのようなイベントが発生しているのかを知りたければ、そのような通知を送信するコードを追加する必要があります。このサンプル スクリプトでは、非常に簡単なフォームの通知を使用することにします。つまり、印刷されたドキュメントの名前と印刷の開始時刻をエコー バックする通知です。コードは次のようになります。

Do While True
    Set objPrintJob = colPrintJobs.NextEvent
    If InStr(objPrintJob.TargetInstance.Name, "atl-color-printer-1") Then 
        Wscript.Echo objPrintJob.TargetInstance.Document, Now
    End If
Loop 

ここでは、永久に実行される Do Loop を設定しました (Do While True は基本的に、True である間はループが実行され続けます)。なぜこの処理を行うのでしょうか。IL さんは、プリンタを常時監視し、ドキュメントが印刷されるたびに通知を受信したいわけですよね。その場合、無限ループ内に通知コードを配置するのが最も簡単な方法です。

次のコード行を見てください。

Set objPrintJob = colPrintJobs.NextEvent

スクリプトがこのコード行に達すると、スクリプトは追跡を停止し、NextEvent の発生を待ちます。もちろんこの場合のイベントとは、Win32_PrintJob クラスの新しいインスタンスの作成です。ドキュメントが印刷されない (そして、このクラスの新しいインスタンスも作成されない) 場合、スクリプトはこの行で永久に待機し、次のイベント発生を律儀に待ち続けます。

次のイベントが発生し、ドキュメントの印刷が行われた場合、何をすればよいのでしょうか。まずは、ドキュメントが対象プリンタで出力されているかどうかをチェックする必要があります。

If InStr(objPrintJob.TargetInstance.Name, "atl-color-printer-1") Then

ここでは InStr 関数を使用します。それは、印刷ジョブ Name が少なくともネットワーク プリンタで\\\\atl-ps-01\\atl-color-printer-1, 226 のようになっているためです。プリンタのネットワーク パスに加え、226 などのジョブ ID が個々の印刷ジョブに割り当てられているため、長大な文字列になります。ここでは、文字列 atl-color-printer-1 が印刷ジョブ Name に含まれているかどうかをチェックします。含まれている場合、ドキュメントはプリンタ atl-color-printer-1 で出力されています。

注 : スクリプトが実行されるコンピュータに接続されているプリンタが 1 台だけであれば、この If-Then ステートメントはスキップしてもかまいません。そのようなケースでは、出力先となるプリンタは 1 台だけでしょうから。

InStr 関数が True を返した場合、つまり文字列 atl-color-printer-1 が見つかった場合は、ドキュメントの名前と印刷の開始時刻をエコー バックします。

Wscript.Echo objPrintJob.TargetInstance.Document, Now

これで終わりです。その後はループに戻り、次のイベントの発生を待ちます。監視を停止する場合は、スクリプトを実行しているプロセス (Cscript.exe または Wscript.exe) を終了します。

また、ドキュメントが印刷されたことをエコー バックする方法の代わりに、.WAV ファイルを再生して音声で通知するスクリプトを記述することもできます。これは、ご自分で試してください。おそらく、「経験済みだ。もう何年も前なのに、まだ耳鳴りがするよ」と言われるでしょう。


関連情報

Hey, Scripting Guy!- アーカイブもチェックしてください。

ページのトップへページのトップへ