VBAからPowerShellのスクリプトをウインドウ非表示で起動する方法を紹介します。
PowerShellを非表示で起動するには、こちらで紹介している通りWSHを経由させます。
pmp-style.hatenablog.com その結果、VBA → WSH → PowerShell というコール順になります。
サンプル
PowerShellのスクリプト "C:\temp\test dir\test.ps1"を、引数 "C:\temp\test dir" を指定して、ウインドウ非表示で起動する。
空白ありのパスなので、ダブルコーテーションが必要です。
VBA, WSH, PowerShellの3言語が要求するダブルコーテーションを満たしてあげなければならず、半日かかって行きついた結果がこれです。もはや暗号にしか見えないコードですね。
最初は1行ですべて書こうとしたらはまってしまい、変数に分離したのとダブルコーテーションをASCIIコードで書くことで動かすことができました。
ps = Chr(34) & "C:\temp\test dir\test.ps1" & Chr(34) arg = Chr(34) & "C:\temp\test dir" & Chr(34) cmdline = """powershell"" -ExecutionPolicy RemoteSigned -File " & ps & " " & arg Dim objWSH As Object Set objWSH = CreateObject("WScript.Shell") objWSH.Run cmdline, 0, True
こりゃサイクロマティック複雑度は低いが、ダブルコーテーション複雑度はMAXだよ。VBAなんて大っ嫌いだ~
しかし、アプリケーション環境としては UIはEXCEL、コードビハインドでVBAと、EXCELがあれば完結してしまうため捨てられない。最近 PowerShell に目覚めて、とても面白いのでロジックは PowerShell で書くようになってきました。
関数化
これでは使いにくいので関数化します。
なるべく汎用化したいので、ウインドウの表示やスクリプトの終了待ちもパラメータ化しました。また、PowerShellのスクリプトへの引数の数も可変引数にすることでいくつでも渡せるようにしてあります。パス名などの半角空白にも対応します。
関数 RunPowerShell
引数
intWindowStyle
Wsh のRun コマンドの第2引数です
値 | 意味 |
---|---|
0 | ウィンドウを非表示にし、別のウィンドウをアクティブにする |
1 | ウィンドウをアクティブにして表示する。ウィンドウが最小化または最大化されている場合は、元のサイズと位置に戻る |
2 | ウィンドウをアクティブにし、最小化ウィンドウとして表示する |
3 | ウィンドウをアクティブにし、最大化ウィンドウとして表示する |
4 | ウィンドウを最新のサイズと位置で表示する。アクティブ・ウィンドウは切り替わらない |
5 | ウィンドウをアクティブにし、現在のサイズと位置で表示する |
6 | 指定したウィンドウを最小化し、Zオーダー上で次に最上位となるウィンドウをアクティブにする |
7 | ウィンドウを最小化ウィンドウとして表示する。アクティブ・ウィンドウは切り替わらない |
8 | ウィンドウを現在の状態で表示する。アクティブ・ウィンドウは切り替わらない |
9 | ウィンドウをアクティブにして表示する。ウィンドウが最小化または最大化されている場合は、元のサイズと位置に戻る |
10 | アプリケーションを起動したプログラムの状態に基づいて表示状態を設定する |
bWaitOnReturn
Wsh のRun コマンドの第3引数です
True: スクリプト実行の終了を待つ(同期実行)
False: スクリプト実行の終了を待たない(非同期実行)
psFilePath
PowerShell スクリプトのファイルパス
args
PowerShellスクリプトへの引数
可変引数なのでいくつでも渡せます
戻り値
bWaitOnReturn がTrueのとき
PowerShellスクリプトの戻り値
bWaitOnReturn がFalseのとき
WshのRun の戻り値
Function RunPowerShell(intWindowStyle As Long, bWaitOnReturn As Boolean, psFilePath As String, ParamArray args()) Dim cmdline As String cmdline = Chr(34) & "powershell" & Chr(34) & " -ExecutionPolicy RemoteSigned -File " & Chr(34) & psFilePath & Chr(34) Dim arg As Variant For Each arg In args cmdline = cmdline & " " & Chr(34) & arg & Chr(34) Next Dim objWSH As Object Set objWSH = CreateObject("WScript.Shell") Dim ret As Variant ret = objWSH.Run(cmdline, intWindowStyle, bWaitOnReturn) RunPowerShell = ret End Function
'呼び出し例 test.ps1をウインドウを表示して同期実行させる ret = RunPowerShell(1, True, "c:\temp dir\test.ps1", "c:\temp dir")
※ ご自由に使っていただいて結構ですが、使用の際はコメントいただけると嬉しいです。サイトへの丸パクリ掲載の場合、このページのリンクを張ることで許可します。