jzb*_*uno 96 powershell start-process
Start-Process访问StandardError和StandardOutput属性时,PowerShell 命令中是否存在错误?
如果我运行以下命令,我得不到输出:
$process = Start-Process -FilePath ping -ArgumentList localhost -NoNewWindow -PassThru -Wait
$process.StandardOutput
$process.StandardError
Run Code Online (Sandbox Code Playgroud)
但是,如果我将输出重定向到文件,我得到预期的结果:
$process = Start-Process -FilePath ping -ArgumentList localhost -NoNewWindow -PassThru -Wait -RedirectStandardOutput stdout.txt -RedirectStandardError stderr.txt
Run Code Online (Sandbox Code Playgroud)
And*_*ndi 116
这就是Start-Process出于某种原因设计的.这是一种在不发送文件的情况下获取它的方法:
$pinfo = New-Object System.Diagnostics.ProcessStartInfo
$pinfo.FileName = "ping.exe"
$pinfo.RedirectStandardError = $true
$pinfo.RedirectStandardOutput = $true
$pinfo.UseShellExecute = $false
$pinfo.Arguments = "localhost"
$p = New-Object System.Diagnostics.Process
$p.StartInfo = $pinfo
$p.Start() | Out-Null
$p.WaitForExit()
$stdout = $p.StandardOutput.ReadToEnd()
$stderr = $p.StandardError.ReadToEnd()
Write-Host "stdout: $stdout"
Write-Host "stderr: $stderr"
Write-Host "exit code: " + $p.ExitCode
Run Code Online (Sandbox Code Playgroud)
JJo*_*nes 20
在问题中给出的代码中,我认为读取启动变量的ExitCode属性应该有效.
$process = Start-Process -FilePath ping -ArgumentList localhost -NoNewWindow -PassThru -Wait
$process.ExitCode
Run Code Online (Sandbox Code Playgroud)
请注意(如在您的示例中)您需要添加-PassThru和-Wait参数(这让我感到有些困难).
小智 11
我也有这个问题,并最终使用Andy的代码创建一个函数来清理需要运行多个命令的东西.
它会将stderr,stdout和退出代码作为对象返回.有一点需要注意:函数不会.\在路径中接受; 必须使用完整路径.
Function Execute-Command ($commandTitle, $commandPath, $commandArguments)
{
$pinfo = New-Object System.Diagnostics.ProcessStartInfo
$pinfo.FileName = $commandPath
$pinfo.RedirectStandardError = $true
$pinfo.RedirectStandardOutput = $true
$pinfo.UseShellExecute = $false
$pinfo.Arguments = $commandArguments
$p = New-Object System.Diagnostics.Process
$p.StartInfo = $pinfo
$p.Start() | Out-Null
$p.WaitForExit()
[pscustomobject]@{
commandTitle = $commandTitle
stdout = $p.StandardOutput.ReadToEnd()
stderr = $p.StandardError.ReadToEnd()
ExitCode = $p.ExitCode
}
}
Run Code Online (Sandbox Code Playgroud)
以下是如何使用它:
$DisableACMonitorTimeOut = Execute-Command -commandTitle "Disable Monitor Timeout" -commandPath "C:\Windows\System32\powercfg.exe" -commandArguments " -x monitor-timeout-ac 0"
Run Code Online (Sandbox Code Playgroud)
小智 7
重要:
我们一直在使用LPG上面提供的功能。
但是,它包含一个错误,您在启动生成大量输出的过程时可能会遇到。因此,使用此功能时可能会陷入死锁。而是使用以下改编版本:
Function Execute-Command ($commandTitle, $commandPath, $commandArguments)
{
Try {
$pinfo = New-Object System.Diagnostics.ProcessStartInfo
$pinfo.FileName = $commandPath
$pinfo.RedirectStandardError = $true
$pinfo.RedirectStandardOutput = $true
$pinfo.UseShellExecute = $false
$pinfo.Arguments = $commandArguments
$p = New-Object System.Diagnostics.Process
$p.StartInfo = $pinfo
$p.Start() | Out-Null
[pscustomobject]@{
commandTitle = $commandTitle
stdout = $p.StandardOutput.ReadToEnd()
stderr = $p.StandardError.ReadToEnd()
ExitCode = $p.ExitCode
}
$p.WaitForExit()
}
Catch {
exit
}
}
Run Code Online (Sandbox Code Playgroud)
可以在MSDN上找到有关此问题的更多信息:
如果父进程在p.StandardError.ReadToEnd之前调用p.WaitForExit,并且子进程写入足够的文本以填充重定向的流,则可能导致死锁。父进程将无限期地等待子进程退出。子进程将无限期等待父进程从完整的StandardError流中读取。
我真的遇到了安迪·阿里斯门迪和LPG这些例子的麻烦.你应该总是使用:
$stdout = $p.StandardOutput.ReadToEnd()
Run Code Online (Sandbox Code Playgroud)
在打电话之前
$p.WaitForExit()
Run Code Online (Sandbox Code Playgroud)
一个完整的例子是:
$pinfo = New-Object System.Diagnostics.ProcessStartInfo
$pinfo.FileName = "ping.exe"
$pinfo.RedirectStandardError = $true
$pinfo.RedirectStandardOutput = $true
$pinfo.UseShellExecute = $false
$pinfo.Arguments = "localhost"
$p = New-Object System.Diagnostics.Process
$p.StartInfo = $pinfo
$p.Start() | Out-Null
$stdout = $p.StandardOutput.ReadToEnd()
$stderr = $p.StandardError.ReadToEnd()
$p.WaitForExit()
Write-Host "stdout: $stdout"
Write-Host "stderr: $stderr"
Write-Host "exit code: " + $p.ExitCode
Run Code Online (Sandbox Code Playgroud)
这是从另一个 powershell 进程(序列化)获取标准输出的一种笨拙方法(“ps 2>&1”也会得到标准错误):
start-process -wait -nonewwindow powershell 'ps | Export-Clixml out.xml'
import-clixml out.xml
Run Code Online (Sandbox Code Playgroud)
让我强调一下-nonewwindow,至少在本地屏幕上获取标准输出和标准错误:
start-process -wait cmd '/c dir' -nonewwindow
Volume in drive C is Windows
Volume Serial Number is 2AC6-626F
Directory of C:\users\me\foo
11/24/2022 11:40 AM <DIR> .
11/24/2022 11:40 AM <DIR> ..
11/24/2022 11:40 AM 330 file.json
1 File(s) 330 bytes
2 Dir(s) 25,042,915,328 bytes free
Run Code Online (Sandbox Code Playgroud)
start-process -wait cmd '/c dir foo' -nonewwindow
Volume in drive C is Windows
Volume Serial Number is 2AC6-626F
Directory of C:\users\me\foo
File Not Found
Run Code Online (Sandbox Code Playgroud)