5

我有一个脚本调用“a.ps1”:

write-host "hello host"
"output object"

我想调用脚本并获取输出对象,但我也希望标准输出被抑制:

$result = .\a.ps1
# Don't want anything printed to the console here

有什么提示吗?

4

3 回答 3

6

确实没有简单的方法可以做到这一点。

一种解决方法是通过定义具有相同名称的函数来覆盖 Write-Host 的默认行为:

function global:Write-Host() {}

这是非常灵活的。它适用于我上面的简单示例。但是,由于某些未知原因,它不适用于我想要应用的实际情况(可能是因为被调用的脚本已签名并且出于安全原因,它不允许调用者任意更改行为)。

我尝试的另一种方法是通过以下方式修改底层控制台的标准输出:

$stringWriter = New-Object System.IO.StringWriter
[System.Console]::SetOut($stringWriter)
[System.Console]::WriteLine("HI") # Outputs to $stringWriter
Write-Host("HI") # STILL OUTPUTS TO HOST :(

但正如你所看到的,它仍然不起作用。

于 2013-01-23T07:03:07.387 回答
0

输出对象 ie "output object" 输出到standard output。所以我不认为你想抑制标准输出。如果你不希望任何东西打印到控制台不要使用Write-Host,因为它会绕过所有流(stdout、stderr、警告、详细, 调试) 并直接显示到主机。目前我知道没有简单的机制可以重定向主机输出。

顺便说一句,如果您不想稍后看到它显示,为什么需要将“hello host”写入控制台?

于 2013-01-23T02:47:56.993 回答
0

好的,我做了一点挖掘。您可以使用:

以下链接

并做:

$result = .\1.ps1 | Select-WriteHost -Quiet
$result[1]

然后选择变量中的第二个对象:

另一种解释

您还可以以一种不会将 Write-Host 更改为 Write-Output 的方式更改脚本,而只是“删除”Write-Host。

完毕...

function Remove-WriteHost
{
   [CmdletBinding(DefaultParameterSetName = 'FromPipeline')]
   param(
     [Parameter(ValueFromPipeline = $true, ParameterSetName = 'FromPipeline')]
     [object] $InputObject,

     [Parameter(Mandatory = $true, ParameterSetName = 'FromScriptblock', Position = 0)]
     [ScriptBlock] $ScriptBlock
   )

   begin
   {
     function Cleanup
     {
       # Clear out our proxy version of Write-Host
       remove-item function:\write-host -ea 0
     }

     function ReplaceWriteHost([string] $Scope)
     {
         Invoke-Expression "function ${scope}:Write-Host { }"
     }

     Cleanup

     # If we are running at the end of a pipeline, need to
     # immediately inject our version into global scope,
     # so that everybody else in the pipeline uses it.
     #
     # This works great, but it is dangerous if we don't
     # clean up properly.
     if($pscmdlet.ParameterSetName -eq 'FromPipeline')
     {
        ReplaceWriteHost -Scope 'global'
     }
   }

   process
   {
      # If a scriptblock was passed to us, then we can declare
      # our version as local scope and let the runtime take it
      # out of scope for us. It is much safer, but it won't
      # work in the pipeline scenario.
      #
      # The scriptblock will inherit our version automatically
      # as it's in a child scope.
      if($pscmdlet.ParameterSetName -eq 'FromScriptBlock')
      {
        . ReplaceWriteHost -Scope 'local'
        & $scriptblock
      }
      else
      {
         # In a pipeline scenario, just pass input along
         $InputObject
      }
   }

   end
   {
      Cleanup
   }
}
$result = .\1.ps1 | Remove-WriteHost

感谢“latkin”的原始功能:)

于 2013-01-24T10:31:08.713 回答