今回の記事では、VBScriptやVBAからPowerShellのps1ファイルを実行し、PowerShellのExitで指定した任意の終了コードを受け取る方法を紹介します。
また、併せてPowerShellのExitの説明や、自動変数の説明、VBScriptやVBAで使用するWshShellオブジェクトについても部分的に解説していきます。
PowerShellの終了コードの指定方法
PowerShellにおいて、スクリプト自体を終了する場合は「Exit」を使用します。
Exitの詳しい仕様は以下のリンク先をご確認ください。
既定値の終了コードは、スクリプトの実行が正常に完了すれば0がセットされ、エラーが発生した場合は1がセットされます。
尚、Exitでは、任意の終了コードを指定することもできます。
# exit 任意の数値
exit 99
PowerShellで簡単な処理を実行して終了するサンプルスクリプトの例を提示します。
# 変数に入れた文字列を指定したテキストファイルに書き込みます。
$message = "Hello World!"
Write-Output $message >> "C:\test.txt"
exit
上記の記述をしたps1ファイルを作成したら、Windows PowerShellを起動し、以下にようにコマンドを実行します。
PS C:\Users\test> C:\test.ps1
このスクリプトを実行すると、Cドライブ直下にテキストファイルが出力されます。
このサンプルコードを更に改造し、正常終了したら終了コードが100,失敗したら200がセットされるようにしてみます。
try
{
# 変数に入れた文字列を指定したテキストファイルに書き込みます。
$message = "Hello World!"
Write-Output $message >> "C:\test.txt"
exit 100
}
catch
{
exit 200
}
尚、この終了コードは整数である必要があります。
アルファベットなどの文字列を終了コードに指定することはできません。
このスクリプトは本来正常終了するため、終了コード:100を返してきているはずですが、この終了コードを受け取るコマンドを使用していないため、終了コードを取得出来ておりません。
Exitで指定した終了コードをPowerShellで取得する方法
PowerShellでは「自動変数」と呼ばれる、PowerShell側で自動的に生成されて値を格納する変数があります。
詳しい説明や、自動変数一覧の解説は以下のリンク先でご確認ください。
前項のExitで明示的に指定した終了コードは、自動変数「$LASTEXITCODE」に格納されます。
「$LASTEXITCODE」は、直近でExitされた際の終了コードを保持します。
PowerShell自体のインスタンス(プロセス)が起動している間のみ有効です。
よって、ps1ファイルを実行した直後に「$LASTEXITCODE」を参照することで、終了コードを取得することが可能になります。
例えば、Windows PowerShellを起動し、以下にようにコマンドを実行することで、PowerShellのコンソールに終了コードを表示できます。
PS C:\Users\test> C:\test.ps1;$LASTEXITCODE
では、これらの内容を踏まえて、この$LASTEXITCODEをVBScriptやVBAで受け取るにはどの様に実装したらよいのかを次項で紹介していきます。
VBSやVBAからps1ファイルを呼び出して終了コードを受け取る方法
当項では、VBSやVBAでPowerShellのps1ファイルを実行して、ps1ファイル内のExitで指定した終了コードを受け取る場合の実装方法を紹介していきます。
尚、当サンプルのポイントは以下になります。
- VBSとVBAでコードを流用できるように参照設定は使わない
- WshShellオブジェクト内のExecメソッドでps1を実行する
- Execメソッド実行時の戻り値はWshScriptExecオブジェクト
- WshScriptExecオブジェクトからストリームで終了コードを取り出す
VBScriptでの実装例
当項では、VBScriptからps1ファイルを実行して、ps1ファイル内のPowerShellで記述したExitの終了コードを受け取る実装例を紹介します。
尚、VBAでも以下のコードを丸っとコピーして、Subプロシージャ化したうえで実行していただければ同様に動きます。
Option Explicit
Dim objWshShell
Dim objWshExec
Dim objStream
Dim lastCode
Dim ps1FileFullName
ps1FileFullName = "C:/test.ps1"
'WshShellオブジェクトを生成します。
Set objWshShell = CreateObject("WScript.Shell")
'WshShellオブジェクトのExecメソッドでPowerShellを起動してps1ファイルを実行します。
Set objWshExec = objWshShell.Exec("powershell " & ps1FileFullName & ";$LASTEXITCODE")
'WshScriptExecオブジェクト内の標準出力を取得します。
Set objStream = objWshExec.StdOut
'ストリームオブジェクトを読み取り、変数に格納します。
lastCode = objStream.ReadAll
'変数の値をMasBoxで表示します。
MsgBox lastCode
Set objStream = Nothing
Set objWshExec = Nothing
Set objWshShell = Nothing
サンプルプログラムの解説
13行目で、PowerShellを起動して、ps1ファイルを実行しています。
尚、WshShellオブジェクトで外部アプリケーションを実行する場合は、今回のサンプルで使用している「Exec」メソッド以外にも、「Run」メソッドも使用できます。
「Run」メソッドでは実行時のウィンドウの制御や、同期、非同期の指定ができるため、外部アプリケーションの実行では「Run」メソッドを使用するケースが多いのですが、「Run」メソッドでは外部アプリケーションからの終了コードを受け取れません。
今回のように、PowerShellなどの外部アプリケーションから終了コードを受け取りたい場合は「Exec」メソッドを使用します。
尚、Execメソッドの実行結果は、WshShellオブジェクトメンバ内のWshScriptExecオブジェクトで戻されてきます。
この「WshScriptExecオブジェクト」内には、プロパティを幾つか持っており、標準出力の値が格納されたプロパティ名は「StdOut」です。
尚、「StdOut」以外にも、「StdErr」や「Status」などのプロパティもあります。
※呼び出し元のVBSやVBAから見ると「入力」ですが、呼び出されたPowerShell側から見ると「出力」です。
15行目ではWshScriptExecオブジェクト内の標準出力結果を変数「objStream」に代入しています。
「WshScriptExecオブジェクト」の「StdOut」プロパティはTextStreamオブジェクトを返すので、Set が必要です。
17行目では、ストリームからReadAllで値を取り出して通常の変数に代入しています。
意図的にエラーを発生させて動作のテスト
当記事で紹介したPowerShellのサンプルスクリプトでは、エラーが発生したら、catch側のExitで指定した終了コードが使われるようにしてあります。
こちらの分岐も確認する場合は、「throw」を使用してみください。
「throw」の詳細については以下で確認してください。
例えば、以下のようにps1ファイルを書き換えます。
try
{
# 変数に入れた文字列を指定したテキストファイルに書き込みます。
$message = "Hello World!"
Write-Output $message >> "C:\test.txt"
# 処理をエラーにします。
throw
exit 100
}
catch
{
exit 200
}
このようにして再度VBScript又はVBAを実行することで、PowerShellは終了コード200を返してくるはずです。
最後に
今回の記事では、VBScriptやVBAからps1ファイルを呼び出して、PowerShellのExitで指定した終了コードを取得する場合の実装方法を紹介しました。
別のアプリケーションからps1ファイルを実行して、その終了コードを取得する方法をインターネットで検索しても、batファイルから呼び出す例しか見つからず、VBSから実装しようとして若干苦労したので記事にしてみました。
今回の記事がどなたかのお役に立てば幸いです。
それでは皆さまごきげんよう!