【问题标题】:PowerShell 2.0 can't redirect stdoutPowerShell 2.0 无法重定向标准输出
【发布时间】:2014-01-05 14:27:39
【问题描述】:

有时,答案是“不”。事实证明这不是一个问题,而更像是一个cri de coeur(好吧,只是抱怨)。

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 中的 2,2, 3, 4, 5, and * in PS3/PS4),适用于 对象流,它是不是 stdout强>。如果stdout 被这个新的对象流概念取代(或者如果 TFS 团队中的某些天才没有决定 cmdlet 应该在所有方向上喷出随机文本噪声作为副作用),这会很好。

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

c:\>powershell .\tfstest.ps1 > nul

但是,我不想抑制整个脚本的所有输出。只是一个 snapin cmdlet 的输出。这不是世界末日,但有一些随机的东西很烦人,我称之为回声垃圾,我无法控制。否则脚本可以正常工作(请参阅更新)。

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

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

更新:这个脚本很脆弱,不可靠,速度极慢,除了我最初编写它的那台计算机之外,不可能在任何计算机上运行。

我将其替换为 Perl 脚本,该脚本的编写时间缩短了 1/10,执行速度提高了 10 倍,并且可以更好地完成相同的任务,而且没有任何愚蠢。 PS 和 TFS PS 管理单元是很棒的想法,但它们都需要大量工作才能准备好发布。

【问题讨论】:

    标签: windows powershell tfs stdout


    【解决方案1】:

    我不熟悉 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】:

      如果您在 > 前面添加 2,它只会重定向错误。同样用 1 表示非错误(标准输出)。所以如果你想要所有的标准输出,而不是标准错误,你可以输入

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

      $null 可以用作 /dev/null 的等价物。您的代码可能会在磁盘上创建文件“nul”。

      【讨论】:

      • 输出重定向记录在about_redirection
      • Get-TfsPendingChange : A positional parameter cannot be found that accepts argument '1>'.
      • 在批处理文件中,nul 带有一个“L”is the null device that you redirect to
      • stderr 部分无关紧要。您的答案中的其他所有内容至少部分错误。 1> 是一个错误。 nul 是众所周知的。使用> 正确重定向到$null 至少不会引发异常,但不幸的是它丢弃了cmdlet 的有用输出,而对stdout 没有影响。 $pcs 在你给出的例子中永远是空的,不会抑制垃圾输出。
      • @EdPlunkett:我相信你很困惑:问题和这个答案都(主要)讨论 PowerShell 脚本,而不是 Cmd 脚本。在 PowerShell 中(根据 vonPryz 发布的链接),2> 和重定向到 $null 都是完全正确的。但是,我怀疑 Snorre 发布的行中缺少括号可能会导致您首先报告的错误。
      猜你喜欢
      • 1970-01-01
      • 2012-05-26
      • 2012-07-11
      • 2017-09-02
      • 2014-02-04
      • 2014-01-20
      • 2011-12-08
      • 1970-01-01
      相关资源
      最近更新 更多