PowerShell: how to intercept (or suppress) a host entry

I have a call script "a.ps1":

write-host "hello host"
"output object"

I want to call a script and get an output object, but I also want standard output to be suppressed:

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

Any hint?

+2
source share
3 answers

There really is no easy way to do this.

The workaround is to override the default Write-Host behavior by defining a function with the same name:

function global:Write-Host() {}

It is very flexible. And this works for my simplified example above. However, for an unknown reason, it does not work in the real case when I wanted to apply (perhaps because the called script is signed and for security reasons it does not allow the caller to arbitrarily change the behavior).

, , - :

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

, , .

+3

ie "output object " standard output. , . , - , Write-Host (stdout, stderr, warning, verbose, debug) . , .

, " " , ?

0

, . :

:

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

:

You can also change the script so that you do not change Write-Host to Write-Output and simply "delete" Write-Host.

Done ...

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 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

Thanks to Latkin for the original feature :)

0
source

Source: https://habr.com/ru/post/1621328/


All Articles