powershell 管道运算符
powershell Pipe Operators
我执行了以下三个 powershell 命令。前两个命令没有返回结果,第三个命令有返回结果。这三个命令之间的主要区别在于等待参数和括号的使用。
PS C:\Users> Start-Process -FilePath 'msiexec' -ArgumentList '/I C:\Users\Downloads\Everything-1.4.1.1015.x64.msi -quiet' -PassThru | Foreach-Object -Process { $_.exitcode }
PS C:\Users> Start-Process -FilePath 'msiexec' -ArgumentList '/I C:\Users\Downloads\Everything-1.4.1.1015.x64.msi -quiet' -PassThru -wait | Foreach-Object -Process { $_.exitcode }
PS C:\Users> (Start-Process -FilePath 'msiexec' -ArgumentList '/I C:\Users\Downloads\Everything-1.4.1.1015.x64.msi -quiet' -PassThru -Wait) | Foreach-Object -Process { $_.exitcode }
1619
我测试了另外两个命令,它们之间的区别在于括号的使用。无论是否带括号,这两个命令都会返回结果。
PS C:\Users> Start-Process -FilePath 'msiexec' -ArgumentList '/I C:\Users\Downloads\Everything-1.4.1.1015.x64.msi -quiet' -PassThru | Foreach-Object -Process { $_.id }
22980
PS C:\Users> (Start-Process -FilePath 'msiexec' -ArgumentList '/I C:\Users\Downloads\Everything-1.4.1.1015.x64.msi -quiet' -PassThru -Wait) | Foreach-Object -Process { $_.id }
8064
感谢您对 -wait 参数的解释。我仍然对括号引起的差异感到困惑。希望多多回复。
The main difference between the three commands is the use of the -Wait
argument and parentheses
以 Mathias R. Jessen 的有用评论为基础:
主要是使用Start-Process
的-Wait
开关:
没有 -Wait
,Start-Process
运行 异步 .
如果没有 -PassThru
,Start-Process
会产生 无输出。
虽然 -PassThru
使 Start-Process
输出代表新启动进程的 System.Diagnostics.Process
实例,除非 -Wait
也是 present 该实例的 .ExitCode
属性 还没有值,因为启动的进程通常 没有退出了.
另外,需要括号((...)
)太,因为Start-Process
将表示新启动进程的 System.Diagnostics.Process
实例发送到管道(由 ForEach-Object
接收)立即, then 等待进程退出。通过使用 (...)
、 分组运算符 ,您将强制等待 Start-Process
本身 退出,此时指向 Process
' 实例 .ExitCode
属性 是 可用,感谢 -Wait
.
一般来说,将命令包装在 (...)
中会强制在 full、up front 中收集其输出 - 这包括等待使其 exit - 在结果通过管道传递之前(与 streaming(逐个输出)行为相反默认情况下,发生 而命令仍然是 运行).
因此,以下方法有效 - 但 请参阅底部部分以获得更简单的替代方法:
# Note: With (...), you could also pipe the output to ForEach-Object, as in
# your question, but given that there's by definition only *one*
# output object, that is unnecessary.
(
Start-Process -PassThru -Wait -FilePath 'msiexec' -ArgumentList '/i C:\Users\Downloads\Everything-1.4.1.1015.x64.msi -quiet'
).ExitCode
从上面可以看出,使用 两个单独的语句 也可以(假设任何语句 运行完成 在执行下一个之前):
$process = Start-Process -PassThru -Wait -FilePath 'msiexec' -ArgumentList '/i C:\Users\Downloads\Everything-1.4.1.1015.x64.msi -quiet'
$process.ExitCode
msiexec.exe
不寻常 在于:
它是一个 GUI(-subsystem) 可执行文件(相对于 console(-subsystem) 可执行文件),因此 - 即使 直接调用 - 运行 异步 .
然而它报告了调用者可能感兴趣的有意义的进程退出代码,要求调用者等待其退出(终止)以便确定此退出代码。
顺便说一句:对于调用 console 应用程序,Start-Process
通常 不是 正确的工具,除了 不寻常 场景 - 参见 this answer。
使用 msiexec
和 Start-Process -PassThru -Wait
的 更简单的替代方法 是 使用 直接 通过 cmd /c
调用,确保 (a) 同步调用 和 (b) PowerShell 在其 automatic $LASTEXITCODE
variable:
cmd /c 'msiexec /i C:\Users\Downloads\Everything-1.4.1.1015.x64.msi -quiet'
$LASTEXITCODE # output misexec's exit code
注意:如果 msiexec
命令行需要包含 PowerShell 变量值,请传递一个 expandable (double-quoted) string ("..."
) to cmd /c
instead and - as with verbatim (single-quoted) string ('...'
) 字符串 - 使用 embedded 双引号围绕嵌入参数,根据需要。
我执行了以下三个 powershell 命令。前两个命令没有返回结果,第三个命令有返回结果。这三个命令之间的主要区别在于等待参数和括号的使用。
PS C:\Users> Start-Process -FilePath 'msiexec' -ArgumentList '/I C:\Users\Downloads\Everything-1.4.1.1015.x64.msi -quiet' -PassThru | Foreach-Object -Process { $_.exitcode }
PS C:\Users> Start-Process -FilePath 'msiexec' -ArgumentList '/I C:\Users\Downloads\Everything-1.4.1.1015.x64.msi -quiet' -PassThru -wait | Foreach-Object -Process { $_.exitcode }
PS C:\Users> (Start-Process -FilePath 'msiexec' -ArgumentList '/I C:\Users\Downloads\Everything-1.4.1.1015.x64.msi -quiet' -PassThru -Wait) | Foreach-Object -Process { $_.exitcode }
1619
我测试了另外两个命令,它们之间的区别在于括号的使用。无论是否带括号,这两个命令都会返回结果。
PS C:\Users> Start-Process -FilePath 'msiexec' -ArgumentList '/I C:\Users\Downloads\Everything-1.4.1.1015.x64.msi -quiet' -PassThru | Foreach-Object -Process { $_.id }
22980
PS C:\Users> (Start-Process -FilePath 'msiexec' -ArgumentList '/I C:\Users\Downloads\Everything-1.4.1.1015.x64.msi -quiet' -PassThru -Wait) | Foreach-Object -Process { $_.id }
8064
感谢您对 -wait 参数的解释。我仍然对括号引起的差异感到困惑。希望多多回复。
The main difference between the three commands is the use of the
-Wait
argument and parentheses
以 Mathias R. Jessen 的有用评论为基础:
主要是使用Start-Process
的-Wait
开关:
没有
-Wait
,Start-Process
运行 异步 .如果没有
-PassThru
,Start-Process
会产生 无输出。
虽然 -PassThru
使 Start-Process
输出代表新启动进程的 System.Diagnostics.Process
实例,除非 -Wait
也是 present 该实例的 .ExitCode
属性 还没有值,因为启动的进程通常 没有退出了.
另外,需要括号((...)
)太,因为Start-Process
将表示新启动进程的 System.Diagnostics.Process
实例发送到管道(由 ForEach-Object
接收)立即, then 等待进程退出。通过使用 (...)
、 分组运算符 ,您将强制等待 Start-Process
本身 退出,此时指向 Process
' 实例 .ExitCode
属性 是 可用,感谢 -Wait
.
一般来说,将命令包装在 (...)
中会强制在 full、up front 中收集其输出 - 这包括等待使其 exit - 在结果通过管道传递之前(与 streaming(逐个输出)行为相反默认情况下,发生 而命令仍然是 运行).
因此,以下方法有效 - 但 请参阅底部部分以获得更简单的替代方法:
# Note: With (...), you could also pipe the output to ForEach-Object, as in
# your question, but given that there's by definition only *one*
# output object, that is unnecessary.
(
Start-Process -PassThru -Wait -FilePath 'msiexec' -ArgumentList '/i C:\Users\Downloads\Everything-1.4.1.1015.x64.msi -quiet'
).ExitCode
从上面可以看出,使用 两个单独的语句 也可以(假设任何语句 运行完成 在执行下一个之前):
$process = Start-Process -PassThru -Wait -FilePath 'msiexec' -ArgumentList '/i C:\Users\Downloads\Everything-1.4.1.1015.x64.msi -quiet'
$process.ExitCode
msiexec.exe
不寻常 在于:
它是一个 GUI(-subsystem) 可执行文件(相对于 console(-subsystem) 可执行文件),因此 - 即使 直接调用 - 运行 异步 .
然而它报告了调用者可能感兴趣的有意义的进程退出代码,要求调用者等待其退出(终止)以便确定此退出代码。
顺便说一句:对于调用 console 应用程序,Start-Process
通常 不是 正确的工具,除了 不寻常 场景 - 参见 this answer。
使用 msiexec
和 Start-Process -PassThru -Wait
的 更简单的替代方法 是 使用 直接 通过 cmd /c
调用,确保 (a) 同步调用 和 (b) PowerShell 在其 automatic $LASTEXITCODE
variable:
cmd /c 'msiexec /i C:\Users\Downloads\Everything-1.4.1.1015.x64.msi -quiet'
$LASTEXITCODE # output misexec's exit code
注意:如果 msiexec
命令行需要包含 PowerShell 变量值,请传递一个 expandable (double-quoted) string ("..."
) to cmd /c
instead and - as with verbatim (single-quoted) string ('...'
) 字符串 - 使用 embedded 双引号围绕嵌入参数,根据需要。