Share via


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

    #>
}