VBAからPowerShellを任意コマンドで実行するため、いろいろ調べて辿り着いた結果を記しました。
コード
Function runPshell(psCmd As String, intVsbl As Integer, waitFlg As Boolean)
'**** VBAからPowerShellを起動し、任意のコマンドを実行する *********
' psCmd : PowerShellコマンド(PowerShell仕様により260文字以内)
' intVsbl : PowerShell画面表示(1)/非表示(0)
' waitFlg : PowerShell実行終了を待つ(True)/待たない(False)
'***************************************************************
Dim objWSH As Object
Set objWSH = CreateObject("WScript.Shell")
objWSH.Run "powershell -NoLogo -ExecutionPolicy RemoteSigned -Command " & psCmd, intVsbl, waitFlg
End Function
使用例として、txtファイルをコピーするコードを示しました。
Option Explicit
Sub TestPs()
Dim sPath As String
Dim dPath As String
Dim psCmd As String
Dim hoge As Variant
sPath = "C:\work\hoge.txt"
dPath = Replace(sPath, "hoge", "huga")
psCmd = "Copy-Item " & sPath & " " & dPath
hoge = runPshell(psCmd, 0, True)
End Sub
コメント
- 参照設定をユーザに操作させたくなかったので
CreateObject("WScript.Shell")
を使っています。 - 変数
intVsbl
でPowerShell画面の表示(1)/非表示(0)を選択できます。 - 変数
waitFlg
でPowerShell実行完了を待つ(True)/待たない(False)を選択できます。 - PowerShellの仕様上、コマンド格納変数
psCmd
の文字長は260文字以内です。パスが深いファイルのコピーなどは注意が必要です。
##開発経緯など
ファイルを圧縮してサーバに転送したい!という仕事での要望に応えるために開発しました。圧縮、転送中もVBAが動くようにできない?という要望から、処理をOSに渡すのがいいと思い、PowerShell使用となりました。
VBAのFileCopy
だとコピー処理完了まで他のことができませんが、PowerShellに渡してしまえばVBAが次の処理に入れるので効率的です。なお、変数waitFlg
でPowerShellの処理完了を待つようにも設定できます。
# 待つならFileCopyでもよくね?というのは置いといて。。。
参考サイトは各機能に特化したコードでしたが、もしかしてコマンド自体を引数で渡せば汎用化できる?と思い今回のFunctionとなりました。
最初は.Execで作っていましたが、PowerShell画面が邪魔!ということで、画面非表示機能を追加するために.Runを採用しました。
開発過程で、PowerShellコマンドに文字長制限があることが分かりました。ファイル転送がうまく行かずよくよく調べると、パスが深すぎて文字長制限に引っかかっていたようでした。Cドライブ直下に転送用フォルダを掘り、対応しました。
ひと段落ついて、さて記事にしようかとふと調べると、ほぼ同じことしているQiita記事を見つけたので一緒に紹介しておきました。
参考サイト
VBAでZIP圧縮と解凍を行う
PowerShell VBAでPowerShellを実行して結果を取得する(Run編)【初実験編08】
VBAからpowershellコマンドを実行(Qiita)