I Hate Write-Host So Much…
Write-Host is evil. It’s just plain evil. In fact, it’s so evil that I learned to make a proxy function for it. What’s a proxy function? Glad you asked. I’m basing my work on this post by Shay Levy.
https://blogs.technet.com/b/heyscriptingguy/archive/2011/03/01/proxy-functions-spice-up-your-powershell-core-cmdlets.aspx
You start with getting effectively a prototype of the cmdlet, a skeleton of what the cmdlet can accept as parameters. However, I seem to have lost the ability to pipe data into it via STDIN. To get the framework of the function, run this:
[System.Management.Automation.ProxyCommand]::Create((New-Object System.Management.Automation.CommandMetaData (Get-Command Write-Host))) | clip.exe
You can also redirect it into a file, but I find it easier to just Ctrl+N a new file in my ISE or PowerGUI and then paste this in. Then, I add the functionality for my ‘improvements’. In the end, my version of it looks like this (look for the '# added this'
comments for the essential changes):
function Write-Host
{
[CmdletBinding(HelpUri='https://go.microsoft.com/fwlink/?LinkID=113426', RemotingCapability='None')]
param(
[Parameter(Position=0, ValueFromPipeline=$true, ValueFromRemainingArguments=$true)]
[System.Object]
${Object},
[switch]
${NoNewline},
[System.Object]
${Separator},
[System.ConsoleColor]
${ForegroundColor},
[System.ConsoleColor]
${BackgroundColor},
[switch]
${Force}) # added this
begin
{
try {
$outBuffer = $null
if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer))
{
$PSBoundParameters['OutBuffer'] = 1
}
if ($Force)
{ # added this
$wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand(
'Microsoft.PowerShell.Utility\Write-Host',
[System.Management.Automation.CommandTypes]::Cmdlet)
$PSBoundParameters.Remove('Force') | Out-Null; # added this
$scriptCmd = {& $wrappedCmd @PSBoundParameters }
}
else
{
$wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand(
'Microsoft.PowerShell.Utility\Write-Output',
[System.Management.Automation.CommandTypes]::Cmdlet) # added this
$scriptCmd = {& $wrappedCmd $PSBoundParameters['Object'] }
}
$steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin)
$steppablePipeline.Begin($PSCmdlet)
} catch {
throw
}
}
process
{
try {
$steppablePipeline.Process($_)
} catch {
throw
}
}
end
{
try {
$steppablePipeline.End()
} catch {
throw
}
}
<#
.ForwardHelpTargetName Write-Host
.ForwardHelpCategory Cmdlet
#>
}