none
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
    2017年3月2日 14:53

回答

  • 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

    2017年3月2日 18:10
    モデレータ
  • PowerShellのバージョンによっては、標準入力を待機する仕様になっているのが、コンソールが閉じない原因のようです。

    (当方のWindows10環境では問題ありませんでした。)

    Set oExec = CreateObject("Wscript.shell").Exec("powershell -NoLogo -ExecutionPolicy RemoteSigned -Command " & command)

    の直後に

    oExec.StdIn.Close

    という行を追加してみてください。

    2017年3月7日 0:56
    モデレータ

すべての返信

  • 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

    2017年3月2日 18:10
    モデレータ
  • 返信遅れて申し訳ございません!

    頂いたコードで問題なく動作する事が出来ました。

    一つ図々しいのですが、呼び出したプロンプトの画面を手動で閉じるのではなく、

    コード化するのは可能でしょうか?

    頂いたコードに「& exit」を追記したのですが、プロンプトが閉じません。

    2017年3月6日 14:04
  • PowerShellのバージョンによっては、標準入力を待機する仕様になっているのが、コンソールが閉じない原因のようです。

    (当方のWindows10環境では問題ありませんでした。)

    Set oExec = CreateObject("Wscript.shell").Exec("powershell -NoLogo -ExecutionPolicy RemoteSigned -Command " & command)

    の直後に

    oExec.StdIn.Close

    という行を追加してみてください。

    2017年3月7日 0:56
    モデレータ
  • 頂いたコードで問題なく動作する事が出来ました。

    この度は誠にありがとうございます。

    これで業務の効率化が出来そうです!

    2017年3月8日 15:44