Tweaking your PowerShell profile - Part 1: showing loading progress

Tl;dr

In this post we look at adding rotating output at the top of the PowerShell window as shown here:

PsLoadProfile

Introduction

Recently I realised that PowerShell was taking a while to load on my machine. I'd been adding more and more things to my profile and wanted a way to easily see what was taking the time (although I had a pretty good idea).

Thoughts

A couple of ideas came to mind pretty quickly. First was good old Write-Host, so I peppered these calls throughout my profile but wasn’t happy with the result as it felt a bit verbose.

image

Next was the idea of using System.Diagnostics.Debug.WriteLine. Since PowerShell is built on .NET, this is pretty easy to do, and I’ve used this in other places to good effect Smile. You can use DebugView from SysInternals to view the output, and in terms of the console window it is pretty unobtrusive. In fact, it is maybe a little too unobtrusive as you only get an indication of progress if you have something like DebugView open.

Then I came back to the fact that PowerShell is built on .NET and had an idea for how to implement the rotating text…

Implementing the rotating text

So, as I’ve mentioned, PowerShell is built on .NET. And in .NET, console applications use System.Console to interact with the console (to read/write text etc). To test this you can enter [Console]::WriteLine(“Test”) Smile

image

At this point an idea was definitely forming, as Console has another method: SetCursorPosition

image

Aside: As shown above, if you don’t include parameters and try executing a function in PowerShell it returns the type info for the function – handy way to check parameters and overloads

We can put this function to work by setting the location to 0,0 (top left) and then immediately writing some output:

pssetcursorposition

Now we can simply wrap that in a function. Note that we’re padding the output to the full width to erase any previous messages that were written.

function OutputStatus($message){
    [Console]::SetCursorPosition(0,0)
    Write-Host $message.PadRight([Console]::BufferWidth)
}

And then we can use OutputStatus “Loading something” in our profile and we get output like this:

 

PsLoadProfile[1]

Show me the code

The code for this is in this gist. The gist also includes tracking messages to display at the end of loading, but hopefully that code doesn’t need an explanation Smile