Center Write-Host Output

Write-Host

It’s great and it’s main purposes is to well write to the host. Nothing more. So often people abuse it and leaving people to rant about it.
E.G. This guy and the “Gurus”
I agree with both of them in terms of displaying data, hands down. However, when it comes to simple informing the admin/user of the script the “it displays and gets rid of that info” is efficient, and interactive (colors).

With that out of the way. I am working on a script to clear web parts from a sharepoint page via powershell.
I always like clean code an usually my scripts are interactive, for other non-interactive scripts I’d stick with Write-Output as described by the scripting guys.
However since I like to display things colorfully and neatly Write-Host is perfect!

The Problem

Turns out there’s no easy way to get-write host to center it’s output, no mater how hard I googled. This reply from James Bernie however kicked off the idea it was possible.
There were actually a decent amount of issues with his propsed idea, when implemented. First we’ll want a static variable of the window size at start of script.
Then it turns out Bernies fancy full integer trick may return whole numbers, but does so as a dang string type. Instead of wasting time dicking around with another method, i simply did this trick of dividing by 1 on the variable.
The final problem with his concept which was driving me nuts for a good while was due to the fact of how padding method actually works.
PadLeft adds spaces to the left of a string.
This is handy for numeric out-put because padding keeps the numbers properlly aligned on the right.
This was exactly the problem I was facing, testing my existing function with a series of dots of different lengths, I found them all to be right aligned, and not centered.
Another issue I found was that the pipe into measure method under an expression based section of code and calling its sub routine of count ($var | measure).count wasn’t returning the correct value.
That line was pretty stupid anyway when you can simply call any variable thats of a string type length method.
And the final nail in the logical coffin, the padding was again aligning more right of center than actual center due to the fact that’s what it was comparing to first in the convert.
So it made more sense to take ((Wdith of screen) – String.Length)/2 + String.Length, this associated with a left and right padding, creates a centered master piece!!
Finally!!Here’s the final thing I had to overcome. My function I wanted to support Write-Host outputs color param.
As it turns out, overloading functions isn’t supported in powershell, but that didn’t stop someone from comming up with a work around!
This guy and his buzz works… Woo Ad-hoc Polymorphism!!! OK OK… here’s my final piece of code for you guys. NOTE I didn’t do fully ad hoc polythingy I cheated and only supprted foreground color via an if else.
If you *burp* want to make it support background and foreground… Uhhhhh.. do it yourself… getting to wasted right now…

#Function to Centeralize Write-Host Output, Just take string variable parameter and pads it
#Nerd Level over 9000!!! Ad-hoc Polymorphic power time!!
$pswwidth = (get-host).UI.RawUI.MaxWindowSize.Width
function Centeralize()
{
  param(
  [Parameter(Position=0,Mandatory=$true)]
  [string]$S,
  [Parameter(Position=1,Mandatory=$false,ParameterSetName="color")]
  [string]$C
  )
    $sLength = $S.Length
    $padamt =  "{0:N0}" -f (($pswwidth-$sLength)/2)
    $PadNum = $padamt/1 + $sLength #the divide by one is a quick dirty trick to covert string to int
    $CS = $S.PadLeft($PadNum," ").PadRight($PadNum," ") #Pad that shit
    if ($C) #if variable for color exists run below
    {    
        Write-Host $CS -ForegroundColor $C #write that shit to host with color
    }
    else #need this to prevent output twice if color is provided
    {
        $CS #write that shit without color
    }
}

Leave a Reply

Your email address will not be published. Required fields are marked *