今回はプログラムを起動するメソッドのほか、ショートカットの作成/管理、特殊フォルダの取得、環境変数の操作方法などについて解説。
今回も前回に引き続き、WshShellのメンバ(プロパティ/メソッド)について解説していくが、今回はWshShellオブジェクトから派生するオブジェクトもいくつか登場する。
■連載目次
第1回 WSHを始めよう
第2回 VBScript基本(1)文字列の入出力
第3回 VBScript基本(2)計算と分岐処理
第4回 関数を使いこなす:文字列、数値、日付
第5回 データ型について理解を深めよう
第6回 VBScriptの配列を極める
第7回 Subプロシージャで処理を定義
第8回 Functionプロシージャで関数を定義
第9回 VBScriptのオブジェクトを使いこなす
第10回 WScriptオブジェクト(1)
第11回 WScriptオブジェクト(2)
第12回 WshShellオブジェクト(1)
第13回 WshShellオブジェクト(2)
第14回 WshShellオブジェクト(3)
第15回 WshNetworkオブジェクト
第16回 FileSystemObjectオブジェクト(1)
第17回 FileSystemObjectオブジェクト(2)
第18回 FileSystemObjectオブジェクト(3)
第19回 TextStream/Dictionaryオブジェクト
第12回で述べたように、WshShellオブジェクトにはアプリケーションを起動するためのメソッドが2つある。RunメソッドとExecメソッドだ。Runメソッドは第12回で解説済みなので、今回はExecメソッドについて解説する。ExecメソッドはRunメソッドとは違い、起動するアプリケーションのウィンドウ・スタイルを変更したりはできないが、スクリプトを通じて起動したアプリケーションと通信できることが特徴である。Execメソッド自体は引数に実行するファイルのパスを取るだけであるが、戻り値(オブジェクト)を返す。それがWshScriptExecオブジェクトである。WshScriptExecオブジェクトを介して起動したアプリケーションと通信することが可能である。
まずは基本的な例を示す。
Option Explicit
Dim objWshShell
Set objWshShell = WScript.CreateObject("WScript.Shell")
'WshScriptExecオブジェクトを格納する変数を宣言
Dim objExec
'メモ帳を実行すると同時にWshScriptExecオブジェクトを変数に格納
Set objExec = objWshShell.Exec("notepad.exe")
'Statusプロパティが0の間、空ループを回す
Do While objExec.Status = 0
WScript.Sleep 100
Loop
'Statusプロパティが1になったらループを抜け終了処理
MsgBox "メモ帳を終了しました"
Set objExec = Nothing
Set objWshShell = Nothing
このスクリプトを実行するとメモ帳が起動し、表示される。メモ帳を閉じると、終了した旨を伝えるメッセージ・ボックスが表示され、終了する。
この例では、WshScriptExecオブジェクトのStatusプロパティが、Execメソッドで起動したアプリケーションが起動中なら0を返し、終了したら1を返すことを利用し、0の間、空のループを回している。アプリケーションを終了するとループを抜け、終了処理に入る。
このように、WshScriptExecオブジェクトを利用すると実行中のアプリケーションの情報を得るなど、通信が可能である。プロパティにはこのほかにも、起動したアプリケーションのプロセスIDを得るProcessIDプロパティがある。プロセスIDが取得できると、第12回で解説した、ウィンドウをアクティブにするAppActivateメソッドの引数に渡すことで、確実にウィンドウをアクティブ化できる。次の例はメモ帳を立ち上げ、アクティブ化し、文字列を入力した後、5秒待って終了する。起動したアプリケーションを終了するにはTerminateメソッドを用いる。
Option Explicit
Dim objWshShell
Set objWshShell = WScript.CreateObject("WScript.Shell")
'WshScriptExecオブジェクトを格納する変数を宣言
Dim objExec
'メモ帳を実行すると同時にWshScriptExecオブジェクトを変数に格納
Set objExec = objWshShell.Exec("notepad.exe")
'もしメモ帳が起動中なら
If objExec.Status = 0 Then
'メモ帳をアクティブ化し、文字コードを送る
ActivateAndSendKeys objExec.ProcessId, "Happy! Lucky! Scripting!!",1000
End If
'5秒待つ。
WScript.Sleep 5000
'もしメモ帳が起動中なら
If objExec.Status = 0 Then
'メモ帳を終了する
objExec.Terminate
End If
Set objExec = Nothing
Set objWshShell = Nothing
'*********************************************************
'用途: 指定したプロセスIDのウィンドウをアクティブにし、指定
' したキー・コードを送り、数ミリ秒待つ
'受け取る値: lngID: プロセスID(Long)
' strKey: 送るキー・コード(String)
' intWait: キー・コードを送った後待つミリ秒数
' (Integer)
'戻り値: 成功したらTrue、失敗したらFalseを返す(Boolean)
'*********************************************************
Function ActivateAndSendKeys(lngID, strKey, intWait)
Dim intCounter
'10回試行する
For intCounter = 1 To 10
'AppActivateメソッドを実行し、戻り値がTrueなら、
If objWshShell.AppActivate(lngID) Then
WScript.Sleep 100
'キー・コードを送る
objWshShell.SendKeys strKey
'intWaitミリ秒待つ。
WScript.Sleep intWait
'成功を意味するTrueを返し、ループを抜ける
ActivateAndSendKeys = True
Exit For
Else
WScript.Sleep 1000
'失敗を意味するFalseを返し、続行
ActivateAndSendKeys = False
End If
Next
End Function
このスクリプトを実行すると、例えば次のようにメモ帳に文字列が入力されて、放置すると5秒後にウィンドウが閉じる。なお以前述べたとおり、Windows XP環境では正常にウィンドウをアクティブ化できない場合がある点をご了承いただきたい。
関数部分は第12回で紹介したものとほぼ同じなので説明は省略する。ここで重要なのは、AppActivateメソッドにobjExec.ProcessIdを引数として渡している点である。ウィンドウ・タイトルで指定していた場合は、同名ウィンドウがあると別のウィンドウにキー・コード送出を「誤爆する(間違って送信する)」危険性があったが、このスクリプトではその問題は解消されている。
また前述のとおり、WshScriptExecオブジェクトには起動したアプリケーションを終了するTerminateメソッドがあり、これを利用してウィンドウを閉じている。ここでは利用していないが、アプリケーションの終了コードであるExitCodeプロパティも利用可能である。
第11回で説明したとおり、WScriptオブジェクトのStdIn、StdOut、StdErrプロパティを使えばWSH(Windows Script Host)自身の標準入出力を読み書きすることができたが、WshScriptExecオブジェクトにもこれらのプロパティがあるので、起動したアプリケーションの標準入出力も読み書き可能である。例えば、IPアドレスなどのネットワーク情報を得るためのコンソール・プログラム「ipconfig.exe」を実行し、その実行結果(標準出力)を文字列として取り出す例をご覧にいれよう。
Option Explicit
Dim objWshShell
Set objWshShell = WScript.CreateObject("WScript.Shell")
Dim objExec
Set objExec = objWshShell.Exec("ipconfig.exe") 'ipconfig.exeを起動
MsgBox objExec.StdOut.ReadAll '標準出力をすべて読み込み、表示
Set objExec = Nothing
Set objWshShell = Nothing
このスクリプトを実行すると、例えば次のようなメッセージ・ボックスが表示される。
ここではStdOutプロパティの返す標準出力のTextStreamオブジェクトが持つReadAllメソッドを呼び出し、すべての出力を読み込んでいる(TextStreamオブジェクトについては今後解説予定)。ここからIPアドレスの値だけを取り出す例を問題としよう。
マーカーで隠れたところを選択してチェックしてみよう。
Option Explicit
Dim objWshShell
Set objWshShell = WScript.CreateObject("WScript.Shell")
Dim objExec, objStdOut, strLine, strIPAddress
strIPAddress = ""
Set objExec = objWshShell.Exec("ipconfig.exe") 'ipconfig.exeを起動
Set objStdOut = objExec.StdOut '標準出力を取得。
Do Until objStdOut.AtEndOfStream 'TextStreamの最後までループ
strLine = objStdOut.ReadLine '1行読む
If InStr(strLine,"IP Address") Then 'IP Addressが含まれる行なら(XP)
'44文字目から後はIPアドレスなので取得
strIPAddress = strIPAddress & Trim(Mid(strLine,44)) & vbCrLf
ElseIf InStr(strLine,"IPv4 アドレス") Then 'IPv4 アドレスなら(Vista)
'35文字目から後はIPアドレスなので取得
strIPAddress = strIPAddress & Trim(Mid(strLine,35)) & vbCrLf
End If
Loop
objStdOut.Close 'TextStreamを閉じる
MsgBox strIPAddress 'IPアドレスを表示
Set objStdOut = Nothing
Set objExec = Nothing
Set objWshShell = Nothing
このスクリプトの結果は、例えば次のようになる。
このように、標準出力を1行ずつ読んで処理することも可能である。なお、このスクリプトは標準状態のWindows XPとWindows Vistaで動作するように作られているが、Windows Server 2003やWindows Server 2008(次期Windows Server OS)などにも対応したり、確実に正しいIPアドレスを取得したりするには正規表現(RegExpオブジェクト)を使うとよい。ここでは詳説しないが、IPアドレスを表す簡略な正規表現パターン(Patternプロパティ)は“\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}”であることを利用して、次のリファレンスなどを参考に対応していただきたい。
以上のように、WshScriptExecオブジェクトを使えばアプリケーションを起動でき、そのアプリケーションと通信できることがお分かりいただけたと思う。
Copyright© Digital Advantage Corp. All Rights Reserved.