Microsoft Office を使用した実際のスクリプト作成

公開日: 2005年6月9日

Microsoft Word を使用した独自のタスク マネージャの構築 (うそでしょ。いいえ、本当です)

Microsoft Office を購入したとき、スプレッドシートに始まって、ワードプロセッサから電子メール クライアントに至るまで、すべてを含むワールドクラスのアプリケーション セットを手に入れたことを実感できたと思います。お気付きでなかったかもしれませんが、長年スクリプト ライタを悩ませていた次のような質問に対する答えも実は手に入れていたのです。「どうすれば、コンピュータで実行中のすべてのアプリケーションと開いているウィンドウの一覧を取得することができますか。」

ここで、コンピュータで実行中のすべてのプロセスの一覧を取得する方法について話しているわけではないことに留意してください。このデータが必要ならば、WMI の Win32_Process クラスを使って取得することができます。Win32_Process を使って、コンピュータで実行中のすべてのプロセス名を取得すると、次のような情報が得られます。

Win32_Process クラス

拡大表示する

この情報には何の問題もありません。実際、コンピュータで実行中のすべてのプロセスの一覧が必要な場合もあります。しかし、タスク マネージャの [アプリケーション] タブにある項目の一覧だけが必要な場合もあります。

Win32_Process クラス

拡大表示する

つまり、開いているウィンドウだけが必要で、実行可能ファイル名ではなくフレンドリ名 (たとえば、hh.exe ではなく "Portable Script Center") を取得したい場合です。しかし、WMI では、この情報にアクセスできませんし、オペレーティング システムに組み込まれたその他のスクリプト オブジェクトもアクセスできません (Shell オブジェクトは、コンピュータで開いているすべてのシェル項目を一覧する手段を提供していますが、それだけです)。

ところが、驚くべきことに、Microsoft Office を使えばこの情報が取得できるのです。Microsoft Word の Application オブジェクトには、コンピュータで実行中のすべてのプロセスのコレクションを返す Tasks プロパティが含まれています。このプロパティと Win32_Process の違いは、Tasks コレクションが、実行可能ファイル名ではなく、プロセスのフレンドリ名を返すことです。これによって、次のような情報を取得できます。

Microsoft Word の Tasks コレクション

拡大表示する

ちょっと待ってください。Tasks コレクション内の各プロセスを表す Task オブジェクトと Win32_Process によって返されたオブジェクトの間には、少なくとも、もう 1 つ違いがあります。以前の記事に書いたとおり、コンピュータで 46 のプロセスが実行されていても、タスク マネージャの [アプリケーション] タブには 11 の項目しか表示されていませんでした。これは、ほとんどのプロセス (ほとんどのサービスを含みます) が非表示ウィンドウで実行されているためです。つまり、このことが、タスク マネージャが [アプリケーション] タブに表示するプロセスを決定する方法なのです。プロセスを実行しているウィンドウが表示されていれば、タスク マネージャは、そのプロセスをアプリケーションとしてリストアップします。ウィンドウが表示されていなければ、そのプロセスはアプリケーションとしてリストアップされません。

メモ   コンピュータで実行中のすべてのプロセスのフレンドリ名を返すスクリプトについては後で説明します。このスクリプトで、実行可能ファイル名を取得したり、コンピュータで実際に何が実行されているかを理解したりすることは困難ですが、フレンドリ名によって、より明確に状況を把握することができます。

Win32_Process では、プロセスが非表示ウィンドウで実行中であるか、そうでないかを知ることはできません。そのため、Win32_Process では、タスク マネージャがアプリケーションとしてマークしたプロセスを識別することができません。しかし、Task オブジェクトには、プロセスが表示ウィンドウで実行中であるか、そうでないかを示す Visible プロパティが含まれています。Visible プロパティを使用すれば、開いているウィンドウとアプリケーションを識別することができます。

実際にこれを実行するスクリプトを以下に示します。

Set objWord = CreateObject("Word.Application")
Set colTasks = objWord.Tasks

For Each objTask in colTasks
    If objTask.Visible Then
        Wscript.Echo objTask.Name
    End If
Next

objWord.Quit

まず、Microsoft Word のインスタンスを作成します。colTasks という名前の変数に Tasks コレクションを代入してから、コレクションを順に読み取る For Each ループを設定します。タスクごとに (つまり、コンピュータで実行中のプロセスごとに)、表示ウィンドウで実行中かどうかをチェックします。次のコード行が、そのような処理を実行します。

If objTask.Visible Then

Visible プロパティが True であれば、そのタスク名を表示します。Visible プロパティが False の場合は (つまり、プロセスが非表示ウィンドウで実行されている場合は)、ループの最初に戻ってコレクション内の次のタスクをチェックします。コレクション全体をチェックしたら、Word を終了し、スクリプトが終わります。

結果は、どうなるでしょうか。そうですね。結果として、タスク マネージャの [アプリケーション] タブとほぼ同じ一覧が得られます。唯一の違いは、Windows 98 から搭載され、実際には [スタート] メニューを参照しているプログラム マネージャが、スクリプトの出力には表示されて、タスク マネージャには表示されないことです。同様に、タスク マネージャ自体は、タスク マネージャの [アプリケーション] タブには表示されませんが、スクリプトの出力には表示されます。

アクティブなウィンドウ

拡大表示する

すごいと思いませんか。プロセスが表示されているかどうかに関係なく、すべてのプロセスの一覧を取得するには、次のようなスクリプトを使用してください。

Set objWord = CreateObject("Word.Application")
Set colTasks = objWord.Tasks

For Each objTask in colTasks
    Wscript.Echo objTask.Name
Next

objWord.Quit

これでは、まだ半分にも達していません。コンピュータで、ソリティア (Solitaire) で遊んでいる人がいるかどうか知りたくありませんか。その場合は、次のように Exists メソッドを使って、Tasks コレクション内に Solitaire があるかどうかを確認します。

Set objWord = CreateObject("Word.Application")
Set colTasks = objWord.Tasks

If colTasks.Exists("Solitaire") Then
    Wscript.Echo "Someone is playing Solitaire."
End If

objWord.Quit

ソリティアで遊ぶのを止めさせたい場合は、次のように Close メソッドを使って、Solitaire をシャットダウンします。

Set objWord = CreateObject("Word.Application")
Set colTasks = objWord.Tasks

If colTasks.Exists("Solitaire") Then
    colTasks("Solitaire").Close
End If

objWord.Quit

または、ソリティアを一番手前に移動して最大化することで、その人を手助けすることもできます。これには、まず、そのウィンドウをアクティブ化してから (Activate メソッドを使用します)、WindowState プロパティを wdWindowStateMaximize (私たちが定義した定数で、値として 1 が代入されています) に設定します。スクリプトは次のようになります。

Const wdWindowStateMaximize = 1

Set objWord = CreateObject("Word.Application")
Set colTasks = objWord.Tasks

If colTasks.Exists("Solitaire") Then
    colTasks("Solitaire").Activate
    colTasks("Solitaire").WindowState = wdWindowStateMaximize
End If

objWord.Quit

ウィンドウを最小化する場合は、wdWindowStateMaximize 定数に値として 2 を代入します。

まだやる気があれば、Task オブジェクトを使用して、Height、Width、Top (ウィンドウの垂直方向の位置をポイント単位で指定します)、Left (ウィンドウの水平方向の位置をポイント単位で指定します) などの他のウィンドウ プロパティにアクセスすることができます。このスクリプトは次のようになります。

Set objWord = CreateObject("Word.Application")
Set colTasks = objWord.Tasks

If colTasks.Exists("Solitaire") Then
    Wscript.Echo "Name: " & colTasks("Solitaire").Name
    Wscript.Echo "Top: " & colTasks("Solitaire").Top
    Wscript.Echo "Left: " & colTasks("Solitaire").Left
    Wscript.Echo "Height: " & colTasks("Solitaire").Height
    Wscript.Echo "Width: " & colTasks("Solitaire").Width
End If

objWord.Quit

次のようなデータが返されます。

Name: Solitaire
Top: 65
Left: 50
Height: 329
Width: 445

これまで、Word はただのメモ用ソフトだと思っていませんでしたか。そんなあなたには、Microsoft からこんな言葉を送ります。「Word は何でもできます。本当ですよ。」

もちろん、Word の Tasks コレクションは Win32_Process クラスを補完することはできても、その代わりになることはできないことを指摘しておく必要があります。これは、Tasks コレクションが返せない大量の情報 (カーネル モード時間、ユーザー モード時間、プロセス ID、ハンドルの数) を、Win32_Process は返すことができるからです。また、Tasks コレクションで取得したプログラムを、Win32_Process 内の対応するプロセスに関連付ける方法については、明らかな方法がわかりません。この方法がわかったら、お知らせします。


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