トップ回答者
PowerShellのコマンドの実行結果をマクロ(VBA)で受け取る事が出来るのでしょうか?

質問
-
ファイルが最新かどうか確認する為にPowerShellのコマンドを用いて、
下記のようなマクロを作成したいのですが、可能でしょうか?
(PowerShellのコマンドの実行結果をマクロで受け取る事が出来るのでしょうか?)
尚、PowerShellのコマンドの実行結果をマクロで受け取る事が出来ない場合、
PowerShellのスクリプトを予め用意して、それをマクロから呼び出す事を想定しています。
'下記コマンドをの実行結果をそれぞれ変数に格納したい
cmdStr1 = "Get-ChildItem ""F:\VBA\02\aaa\111.txt"" | Select-Object LastWriteTime"
cmdStr2 = "Get-ChildItem ""F:\VBA\02\bbb\111.txt"" | Select-Object LastWriteTime"
CreateObject("Wscript.shell").Run "powershell -ExecutionPolicy RemoteSigned -Command " & cmdStr1
CreateObject("Wscript.shell").Run "powershell -ExecutionPolicy RemoteSigned -Command " & cmdStr2
'上記コマンドで取得した変数の結果を比較して、タイムスタンプが異なっていれば「NG」としたい
If a1 <> a2 Then
MsgBox "NG"
End If
回答
-
Runメソッドの代わりに、Execメソッドを用いてみてはいかがでしょうか。こちらだと標準出力経由でコマンドの実行結果を取得できます。
日付時刻を表す文字列だけ出力したいので、Select-Objectの-ExpandPropertyパラメータを利用すると良いでしょう。あとpowershell.exeのバージョン情報等が出力されないように-NoLogoパラメータを付与します。
それとExecメソッドは非同期的に実行されるので、終了を待機するのにWin32APIのSleep関数を使います。
まとめると以下のような感じになると思います。
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) Private Sub test() Dim cmdStr1 As String, cmdStr2 As String cmdStr1 = "Get-Item ""F:\VBA\02\aaa\111.txt"" | Select-Object -ExpandProperty LastWriteTime" cmdStr2 = "Get-Item ""F:\VBA\02\bbb\111.txt"" | Select-Object -ExpandProperty LastWriteTime" Dim a1 As String, a2 As String a1 = ExecCommand(cmdStr1) a2 = ExecCommand(cmdStr2) If a1 <> a2 Then MsgBox "NG" End If End Sub Private Function ExecCommand(command As String) As String Dim oExec As Object Set oExec = CreateObject("Wscript.shell").Exec("powershell -NoLogo -ExecutionPolicy RemoteSigned -Command " & command) Do While oExec.Status = 0 Sleep 100 Loop ExecCommand = oExec.StdOut.ReadAll End Function
- 回答の候補に設定 Hebikuzure aka Murachi AkiraMVP 2017年3月3日 6:58
- 回答としてマーク 栗下 望Microsoft employee, Moderator 2017年3月9日 0:10
-
PowerShellのバージョンによっては、標準入力を待機する仕様になっているのが、コンソールが閉じない原因のようです。
(当方のWindows10環境では問題ありませんでした。)
Set oExec = CreateObject("Wscript.shell").Exec("powershell -NoLogo -ExecutionPolicy RemoteSigned -Command " & command)
の直後に
oExec.StdIn.Close
という行を追加してみてください。
- 編集済み 牟田口大介Moderator 2017年3月7日 1:05
- 回答としてマーク 栗下 望Microsoft employee, Moderator 2017年3月9日 0:10
すべての返信
-
Runメソッドの代わりに、Execメソッドを用いてみてはいかがでしょうか。こちらだと標準出力経由でコマンドの実行結果を取得できます。
日付時刻を表す文字列だけ出力したいので、Select-Objectの-ExpandPropertyパラメータを利用すると良いでしょう。あとpowershell.exeのバージョン情報等が出力されないように-NoLogoパラメータを付与します。
それとExecメソッドは非同期的に実行されるので、終了を待機するのにWin32APIのSleep関数を使います。
まとめると以下のような感じになると思います。
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) Private Sub test() Dim cmdStr1 As String, cmdStr2 As String cmdStr1 = "Get-Item ""F:\VBA\02\aaa\111.txt"" | Select-Object -ExpandProperty LastWriteTime" cmdStr2 = "Get-Item ""F:\VBA\02\bbb\111.txt"" | Select-Object -ExpandProperty LastWriteTime" Dim a1 As String, a2 As String a1 = ExecCommand(cmdStr1) a2 = ExecCommand(cmdStr2) If a1 <> a2 Then MsgBox "NG" End If End Sub Private Function ExecCommand(command As String) As String Dim oExec As Object Set oExec = CreateObject("Wscript.shell").Exec("powershell -NoLogo -ExecutionPolicy RemoteSigned -Command " & command) Do While oExec.Status = 0 Sleep 100 Loop ExecCommand = oExec.StdOut.ReadAll End Function
- 回答の候補に設定 Hebikuzure aka Murachi AkiraMVP 2017年3月3日 6:58
- 回答としてマーク 栗下 望Microsoft employee, Moderator 2017年3月9日 0:10
-
PowerShellのバージョンによっては、標準入力を待機する仕様になっているのが、コンソールが閉じない原因のようです。
(当方のWindows10環境では問題ありませんでした。)
Set oExec = CreateObject("Wscript.shell").Exec("powershell -NoLogo -ExecutionPolicy RemoteSigned -Command " & command)
の直後に
oExec.StdIn.Close
という行を追加してみてください。
- 編集済み 牟田口大介Moderator 2017年3月7日 1:05
- 回答としてマーク 栗下 望Microsoft employee, Moderator 2017年3月9日 0:10