PowerShell 2.0 无法重定向标准输出



有时,答案是"否"。事实证明,这不是一个问题,而更像是一个呐喊(好吧,只是抱怨)。

Team Foundation Server 2010 PowerShell 管理单元导出一个名为 Get-TfsPendingChange 的 cmdlet,它执行它听起来的样子。

如果没有挂起的更改,Get-TfsPendingChange在标准输出上回显"没有挂起的更改"。我从来没有要求过。以下抑制该输出的尝试均失败:

$pcs = $(Get-TfsPendingChange -Server $server "$/foo/bar" -User $env:USERNAME -r ) | out-null;
$($pcs = Get-TfsPendingChange -Server $server "$/foo/bar" -User $env:USERNAME -r ) | out-null;
$pcs = Get-TfsPendingChange -Server $server "$/foo/bar" -User $env:USERNAME -r | out-null;

我没有收到错误,但文本输出没有重定向。重定向的是 cmdlet 的正常成功输出,如果存在要返回的挂起更改。唯一可以抑制的输出是有用的输出。如果挂起的更改为零,则通过 stdout 获得文本垃圾。如果有任何实际的挂起更改,该流(对象,而不是文本)可以重定向到空设备,但这比无用更糟糕。

因此,stdout 上的文本似乎是此 cmdlet 的副作用,而不是 cmdlet 的输出,并且无法在 PowerShell 中重定向。PowerShell 重定向运算符 >| ,没有 fileno 说明符(PS2、PS2、2、3、4、5 和 PS3/PS4 中的 * 中的 2),在对象流上工作,这不是stdout。如果stdout已被此新的对象流概念取代(或者如果 TFS 团队中的某些天才没有决定 cmdlet 应向各个方向喷出随机文本干扰作为副作用),那就太好了。

垃圾输出肯定在stdout,而不是stderr。当我从 cmd.exe 运行它时,我可以将整个脚本的标准输出重定向到 nul ,并且按预期工作,因为 duh:

c:>powershell .tfstest.ps1 > nul

但是,我不想抑制整个脚本的所有输出。只是一个管理单元 cmdlet 的输出。这不是世界末日,但有随机的东西是令人恼火的,我称之为回声垃圾,我无法控制。否则,脚本将正常工作(请参阅更新)。

一种解决方法是用一些任意字符串(比如"KLUDGEPREFIX")在stdout上回显的所有内容,并从批处理文件中运行整个混乱,该文件通过find /v KLUDGEPREFIX管道传输 PowerShell 脚本的输出,然后通过 PowerShell 片段从每行中删除前缀。

相反,我将围绕这个问题编写脚本的其余部分,这样看起来他们得到的是我想要的,因为事实上,我要告诉他们他们无论如何都没有任何待处理的更改。然而,就让我的头脑进入PowerShell而言,这是一个有价值的练习。

更新:这个脚本被证明是脆弱的,不可靠的,冰川般的缓慢,并且不可能在任何计算机上运行,除了我最初编写它的那台计算机。

我用一个 Perl 脚本替换了它,它花了 1/10 的时间来编写,执行速度提高了 10 倍,并且可以更好地完成相同的任务,没有任何愚蠢的行为。PS 和 TFS PS 管理单元是好主意,但它们都需要大量工作才能准备好发布。

我不熟悉 Team Foundation Server,但很可能是 cmdlet 写入主机而不是输出流之一。主机的输出无法在 PowerShell 中重定向,但如果在 CMD 中运行 PowerShell 脚本,主机输出将转到 STDOUT(成功输出流也是如此),并且可以重定向到那里。

示范:

PS C:> cat .test.ps1
Write-Host 'foo'
PS C:> .test.ps1 | Out-Null
foo
PS C:> .test.ps1 >$null
foo
PS C:> & cmd.exe /c powershell.exe -File .test.ps1
foo
PS C:> & cmd.exe /c powershell.exe -File .test.ps1 `>nul
PS C:> & cmd.exe /c powershell.exe -File .test.ps1 >$null
PS C:> _

如果在>前面添加 2,它只会重定向错误。 同样,1 表示非错误 (stdout)。因此,如果您希望所有标准输出,而不是标准输出,您可以键入

$pcs = Get-TfsPendingChange -Server $server "$/foo/bar" -User $env:USERNAME -r 1> $null

$null可以用作/dev/null 的等效项。 您的代码可能会在磁盘上创建文件"nul"。