簡體   English   中英

PowerShell:如何捕獲(或抑制)寫主機

[英]PowerShell: how to capture (or suppress) write-host

我有一個腳本調用“a.ps1”:

write-host "hello host"
"output object"

我想調用腳本並獲取輸出對象,但我還希望抑制標准輸出:

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

任何提示?

真的沒有簡單的方法可以做到這一點。

解決方法是通過定義具有相同名稱的函數來覆蓋Write-Host的默認行為:

function global:Write-Host() {}

這非常靈活。 它適用於我上面簡單的例子。 但是,由於某些未知原因,它不適用於我想要應用的實際情況(可能因為被調用的腳本已簽名,並且出於安全原因,它不允許調用者任意更改行為)。

我嘗試的另一種方法是通過以下方式修改底層Console的標准輸出:

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

但正如你所看到的,它仍然無效。

輸出對象即"output object ”輸出到standard output 所以我認為你不想壓制標准輸出。 如果您不希望在控制台上打印任何內容,請不要使用Write-Host因為它會繞過所有流(stdout,stderr,warning,verbose,debug)並直接顯示給主機。 目前還沒有我想知道的重定向主機輸出的簡單機制。

順便說一句,如果你不想在以后看到它,你為什么需要在控制台上寫“hello host”?

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

以下鏈接

並做:

$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”的原始功能:)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM