26 votes

Powershell : Capturer les sorties et erreurs standard avec l'objet Process

Je veux lancer un programme Java à partir de PowerShell et obtenir les résultats imprimés sur la console.

J'ai suivi les instructions de cette question : Capture de la sortie standard et de l'erreur avec Start-Process

Mais pour moi, cela ne fonctionne pas comme prévu. Qu'est-ce que je fais de mal ?

C'est le script :

$psi = New-object System.Diagnostics.ProcessStartInfo
$psi.CreateNoWindow = $true
$psi.UseShellExecute = $false
$psi.RedirectStandardOutput = $true
$psi.RedirectStandardError = $true
$psi.FileName = 'java.exe'
$psi.Arguments = @("-jar","tools\compiler.jar","--compilation_level",   "ADVANCED_OPTIMIZATIONS", "--js", $BuildFile, "--js_output_file", $BuildMinFile)
$process = New-Object System.Diagnostics.Process
$process.StartInfo = $psi
$process.Start() | Out-Null
$process.WaitForExit()
$output = $process.StandardOutput.ReadToEnd()
$output

Le site $output est toujours vide (et rien n'est imprimé sur la console bien sûr).

45voto

Keith Hill Points 73162

Les documents sur le RedirectStandardError suggère qu'il est préférable de mettre la propriété WaitForExit() après l'appel ReadToEnd() appel. Ce qui suit fonctionne correctement pour moi :

$psi = New-object System.Diagnostics.ProcessStartInfo 
$psi.CreateNoWindow = $true 
$psi.UseShellExecute = $false 
$psi.RedirectStandardOutput = $true 
$psi.RedirectStandardError = $true 
$psi.FileName = 'ipconfig.exe' 
$psi.Arguments = @("/a") 
$process = New-Object System.Diagnostics.Process 
$process.StartInfo = $psi 
[void]$process.Start()
$output = $process.StandardOutput.ReadToEnd() 
$process.WaitForExit() 
$output

18voto

Paul Viscovich Points 181

Une petite variation pour que vous puissiez imprimer sélectivement la sortie si nécessaire. Par exemple, si vous ne cherchez que des messages d'erreur ou d'avertissement, et au fait, Keith, vous m'avez sauvé la mise avec votre réponse...

$psi = New-object System.Diagnostics.ProcessStartInfo 
$psi.CreateNoWindow = $true 
$psi.UseShellExecute = $false 
$psi.RedirectStandardOutput = $true 
$psi.RedirectStandardError = $true 
$psi.FileName = 'robocopy' 
$psi.Arguments = @("$HomeDirectory $NewHomeDirectory /MIR /XF desktop.ini /XD VDI /R:0 /W:0 /s /v /np") 
$process = New-Object System.Diagnostics.Process 
$process.StartInfo = $psi 
[void]$process.Start()
do
{
   $process.StandardOutput.ReadLine()
}
while (!$process.HasExited)

4voto

Justin Points 171

Voici une modification de la réponse de Paul, en espérant que cela règle le problème de la sortie tronquée. J'ai fait un test en utilisant un échec et je n'ai pas vu de troncature.

function Start-ProcessWithOutput
{
    param ([string]$Path,[string[]]$ArgumentList)
    $Output = New-Object -TypeName System.Text.StringBuilder
    $Error = New-Object -TypeName System.Text.StringBuilder
    $psi = New-object System.Diagnostics.ProcessStartInfo 
    $psi.CreateNoWindow = $true 
    $psi.UseShellExecute = $false 
    $psi.RedirectStandardOutput = $true 
    $psi.RedirectStandardError = $true 
    $psi.FileName = $Path
    if ($ArgumentList.Count -gt 0)
    {
        $psi.Arguments = $ArgumentList
    }
    $process = New-Object System.Diagnostics.Process 
    $process.StartInfo = $psi 
    [void]$process.Start()
    do
    {

       if (!$process.StandardOutput.EndOfStream)
       {
           [void]$Output.AppendLine($process.StandardOutput.ReadLine())
       }
       if (!$process.StandardError.EndOfStream)
       {
           [void]$Error.AppendLine($process.StandardError.ReadLine())
       }
       Start-Sleep -Milliseconds 10
    } while (!$process.HasExited)

    #read remainder
    while (!$process.StandardOutput.EndOfStream)
    {
        #write-verbose 'read remaining output'
        [void]$Output.AppendLine($process.StandardOutput.ReadLine())
    }
    while (!$process.StandardError.EndOfStream)
    {
        #write-verbose 'read remaining error'
        [void]$Error.AppendLine($process.StandardError.ReadLine())
    }

    return @{ExitCode = $process.ExitCode; Output = $Output.ToString(); Error = $Error.ToString(); ExitTime=$process.ExitTime}
}

$p = Start-ProcessWithOutput "C:\Program Files\7-Zip\7z.exe" -ArgumentList "x","-y","-oE:\PowershellModules",$NewModules.FullName -verbose
$p.ExitCode
$p.Output
$p.Error

Le sommeil de 10ms est pour éviter de faire tourner le cpu quand il n'y a rien à lire.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X