I have a script call \"a.ps1\":
write-host \"hello host\"
\"output object\"
I want to call the script and obtain the output object, but I a
The output object i.e. "output object
" is output to standard output
. So I don't think you want to suppress standard output. If you don't want anything printed to the console don't use Write-Host
as that bypasses all streams (stdout, stderr, warning, verbose, debug) and displays directly to the host. There is currently no easy mechanism I'm aware of to redirect host output.
BTW why do you need to write "hello host" to the console if you don't want to see it displayed later?
OK, I did a little digging over it. You can use:
The Following Link
And do:
$result = .\1.ps1 | Select-WriteHost -Quiet
$result[1]
And then select the second object in the variable:
Another explanation
You can also change the script in a way that will not change Write-Host to Write-Output and just "remove" the 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'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
Thanks to "latkin" for the original function :)
There really is no easy way to do this.
A workaround is to override the default behavior of Write-Host by defining a function with the same name:
function global:Write-Host() {}
This is very flexible. And it works for my simplistic example above. However, for some unknown reason, it doesn't work for the real case where I wanted to apply (maybe because the called script is signed and for security reasons it doesn't allow caller to arbitrarily change the behavior).
Another way I tried was to modify the underlying Console's stdout by:
$stringWriter = New-Object System.IO.StringWriter
[System.Console]::SetOut($stringWriter)
[System.Console]::WriteLine("HI") # Outputs to $stringWriter
Write-Host("HI") # STILL OUTPUTS TO HOST :(
But as you can see, it still doesn't work.