none
start-processの受け渡し

    質問

  • 外部コマンドを終了するまで待ちながら、

    ・実行結果を画面上に標準出力
    ・結果を変数に格納
    ・変数の内容により条件分岐させる

    という事をしたいのですが、

    $a = start-proess -filepath 外部コマンド -argumentlist オプション -PassThru -wait -nonewwindow hidden

    などとしているのですが、実行結果の標準出力の仕方が分からず困っています。
    また、start-processを使用せずに次の処理まで待たせるような書き方というのはあるのでしょうか。





    • 編集済み miles555 2018年6月13日 21:17
    2018年6月13日 20:22

すべての返信

  • PowerShellでは外部コマンドも、コマンドレットと同様にPowerShellのコマンドとして実行することが可能です。外部コマンドの標準出力を文字列として取得することも可能です。

    また、Tee-Objectコマンドレットを用いると、外部コマンドによる標準出力の内容をコンソールに出力すると同時に、文字列として変数に格納することが可能です。

    これらを組み合わせると、以下のようなスクリプトで、外部コマンドの実行結果を表示しつつ、$resultという変数に格納することが可能となります。

    外部コマンド オプション | Tee-Object -Variable result

    Start-Processコマンドレットだと、 -RedirectStandardOutputパラメータを用いて、ファイルに標準出力の内容をリダイレクトすることは可能ですが、標準出力の内容を文字列として変数に格納することはできないように思います。

    2018年6月14日 0:41
    モデレータ
  • .NETのProcessオブジェクトを使うのがいいんじゃないでしょうか。

    $p = New-Object System.Diagnostics.Process
    $p.StartInfo.FileName = $command
    $p.StartInfo.Arguments = $arguments
    $p.StartInfo.UseShellExecute = $false
    $p.StartInfo.CreateNoWindow = $true
    $p.StartInfo.RedirectStandardOutput = $true
    $p.Start()
    $p.WaitForExit()
    $result = $p.StandardOutput.ReadToEnd()
    Write-Host $result

    2018年6月14日 0:43
  • アドバイスありがとうございます。
    私も同様の方法を見つけて試しておりました。
    外部コマンドの戻り値も$p.exitcodeで取ろうとしたのですが、
    別のコードが出てしまっていて原因を調べています。
    2018年6月17日 11:01
  • この場合どのように戻り値を取得すか調べているのですが、中々わからない状態です。

    $LASTEXITCODE変数に格納されます。

    // ついteeが-Variableを取れることを忘れちゃう…。

    2018年6月17日 11:45
  • アドバイスありがとうございます。
    私も試していたのですが、start-processでは文字列格納までは出来ないように感じました。
    tee-objectだと格納と標準出力両々取ってくれますね。
    これと組み合わせて外部コマンド自体が出す戻り値を、条件式に入れ分岐させたいと思っているのですが、
    この場合どのように戻り値を取得すか調べているのですが、中々わからない状態です。
    2018年6月18日 15:10
  • 質問文が曖昧で適切な回答ができない状況に見受けられます。まず外部プロセスが出力するのは、標準出力(文字列もしくはバイナリ)とExitCode(32bit値)があります。質問者さんはどちらを求めているのか明確に示されていません。

    その上で、標準出力であれば Tee-Object で得られ、ExitCodeであれば $LASTEXITCODE で得られます。

    2018年6月18日 23:12
  • 意図した値が取れていないとのことなので、一旦別のファイルに格納して内容を確認してみてはどうでしょうか。
    1行目が改行だったりとかでうまく動いていないだけかも。
    exitcode で別のコードが出ているのは、内部で複数のコマンドを実行しているとか、
    そのコマンドがそもそもコードを返していないというケースがあります。

    エラーと標準出力はストリームが違うので、順番は保証されないので注意が必要です。
    例えば「エラー1 , 標準出力2, エラー3」 という順で発生した場合、以下の方法だと
    「標準出力2,エラー1,エラー2」と表示されます。

    なお -WindowStyle Hidden / -NoNeWindow どちらかしか使えないです。

    # 一時ファイル
    # ユーザの一時フォルダの一時ファイルのパスが自動で作られる
    $StdOutPath = [System.IO.Path]::GetTempFileName()
    $StdErrPath = [System.IO.Path]::GetTempFileName()
    
    # 実行。HiddenとNoNewWindowは排他なのでHiddenの例。
    $proc = Start-Process 	外部コマンド `
                -WindowStyle Hidden `
                -ArgumentList オプション `
                -PassThru `
    	        -RedirectStandardOutput $StdOutPath `
    	        -RedirectStandardError $StdErrPath `
    	        -Wait
    
    # このプロセスのExitCodeで分岐する場合
    if($Proc.ExitCode -eq 0)
    {
    	# ExitCodeが0の場合の処理
    }
    
    # 標準出力とエラー出力の内容は一時ファイルに保存されているので
    # 変数に格納したいのであればそれを読み込めばOK
    $StdOutString = Get-Content $StdOutPath
    $StdErrString = Get-Content $StdErrPath
    
    #実行結果を画面上に標準出力
    Write-Host $StdOutString
    Write-Host $StdErrString
    
    # 後始末
    Remove-Item $StdOutPath
    Remove-Item $StdErrPath
    

    2018年8月15日 2:09
  • Start-ProcessではなくInvoke-Commandを使用してはどうですか?

    PS C:\Users\osamu> $a = Invoke-Command -ScriptBlock {ping 127.0.0.1}
    PS C:\Users\osamu> $a
    
    127.0.0.1 に ping を送信しています 32 バイトのデータ:
    127.0.0.1 からの応答: バイト数 =32 時間 <1ms TTL=128
    127.0.0.1 からの応答: バイト数 =32 時間 <1ms TTL=128
    127.0.0.1 からの応答: バイト数 =32 時間 <1ms TTL=128
    127.0.0.1 からの応答: バイト数 =32 時間 <1ms TTL=128
    
    127.0.0.1 の ping 統計:
        パケット数: 送信 = 4、受信 = 4、損失 = 0 (0% の損失)、
    ラウンド トリップの概算時間 (ミリ秒):
        最小 = 0ms、最大 = 0ms、平均 = 0ms

    戻り値に標準出力が入ります。引数を渡すこともできるので詳しくは「Invoke-Command -?」で見てみてください。

    なお、ScriptBlock内に複数行のコードを書くこともできます。

    2018年8月16日 7:44
  • サンプルです。
    $res = Invoke-Command -ArgumentList "127.0.0.1",6 -ScriptBlock {
        ping -n $args[1] $args[0]
        Write-Output $LASTEXITCODE
    }
    "<標準出力>"
    $res[0..($res.Length - 2)]
    "<結果>"
    $res[$res.Length - 1]
    

    2018年8月16日 8:14