/*Google AdSense自動広告*/

2018年12月10日月曜日

VBAのWscript.shellから実行したPowerShellスクリプトのエラーをcatchしてVBAに返す方法

VBAからPowerShellスクリプトを実行することは簡単でしたが、スクリプトの結果を取得し、エラーをキャッチして動作を止める際につまづいてしまいました。仕様が悪いのか、私の知識不足なのか…。ちょっとクセがあるので、解決法を説明します。





PowerShellでtry~catchを使う際はErrorAction設定を忘れずに

例えば、あるスクリプトでファイルをエクスポートする前に、古いファイルを消去する時、Remove-Itemに-Forceオプションを付けても、ファイルが開かれている場合は失敗します。このオプションは隠し/読み取り専用ファイルも消せるだけなのですね。

そこで、失敗したら実行を止め、エラー値を返して終了すべきところ。しかし、catch文に入ってくれない。これは、デフォルト設定が「エラー時に継続(ErrorAction:Continue)」であることが原因でした。

その為、catchするにはtry文に必ず「-ErrorAction:Stop」を付けるか、最初に「$ErrorActionPreference = "Stop"」の一文を加えて全てのコマンドでStopするようにしなければいけません。

catchしたら、「exit 数値」でエラーコードを吐き出してスクリプトを終了します。正常終了は「exit 0」なので、それ以外の分かりやすい数値を自分で決めます。

$ROOT_FOLDER=Split-Path $MyInvocation.MyCommand.Path -parent
$SAVE_FOLDER="$ROOT_FOLDER\output"

try{
    Remove-Item $SAVE_FOLDER\*.* -Force -ErrorAction:Stop
}catch{
    exit 1
}finally{

}

#ファイルエクスポート処理など
exit 0



VBAからPowerShellスクリプトを実行し、エラーをcatchする

例えば、先のスクリプトをAccess VBAから実行し、ファイルをインポートしてクエリでテーブルを作る場合、スクリプトの失敗をcatchできないと不完全なテーブルが出来てしまうので、スクリプトの返り値で処理を中止する必要があります。

VBAからPowerShellスクリプトを実行するには、Wscript.shellのRunを使います。引数は左から

  • コマンドライン(ファイル名含めたフルパス)
  • ウィンドウを表示するなら1/非表示0
  • スクリプトの終了を待つならTrue/即座にVBAに戻るならFalseで、必ず0を返す


今回は、ファイルのエクスポートを待つ必要があるので、最後のオプションはTrueとします。

適当な変数にWscriptの結果を代入してやれば、スクリプトの返り値がわかるので、0以外なら中止にするような条件分岐が可能です。

Public Sub ImportFiles()
    Dim Wsh, script_result
    Set Wsh = CreateObject("Wscript.shell")
    
    script_result = Wsh.Run("powershell -ExecutionPolicy RemoteSigned -Command " & script_path, 1, True)

    If script_result = 1 Then
            MsgBox "スクリプトが失敗しました"
            Exit Sub
    End If

    'ファイルインポート処理など

End Sub



2 件のコメント:

  1. 実行コマンドの部分はどこですか?

    返信削除
  2. VBAで管理者でPwershellを実行するコードを知りたいです

    返信削除