PowerShell profile recommendations

As the (very few ;-)) followers of my previous blog know – I am a big PowerShell fan. Love it. Love it.

When I am configuring a new system, I spend a little time configuring my PowerShell environment (which is generally where I spend most of my time). This post is about the recommendations I have around configuring a base profile. Obviously your tastes may vary, but here is what I like as a starter configuration.

NB: If you’re not familiar with PowerShell profiles, please use the command “help about_profiles”.

For this discussion, I am using a Windows 8.1 box with no previous PowerShell configuration. So – first thing is to update to PowerShell 5.0 (at the time of this writing, that is available here: http://www.microsoft.com/en-us/download/confirmation.aspx?id=48729). This is not strictly required but I like to stay current with my environment.

Okay – let’s get started.

First and most important step, open (one of [1]) your profile(s).  You can do this with this command (which can all be placed on one line – but I formatted thusly for readability):

if(Test-Path $profile ) {
notepad $profile
} else {
new-item -type file -path $profile -force
notepad $profile

Note very impressive, but it does open an empty notepad without giving you an error. 😉

Most Important: Let’s get a history going. For me, the most important thing is to record everything I do at all times.  One never knows when one must go back and answer the question: “WTF did I do?!”.  So here’s the snippet of code to add to the profile which makes that happen.

# Create new transcripts directory
if(-not (test-path c:\Transcripts)) {
New-Item -Type Directory -Path c:\Transcripts -Force
Start-Transcript -Path C:\Transcripts\$(get-date -format yyyyMMddhhmmss).txt

Let’s look at this line by line.

  1. A comment stating our purpose
  2. See if our target directory does not exist…
  3. If not, then create a new directory (C:\Transcripts)
  4. n/a
  5. Go ahead and start the transcript in the target directory. I use a PoSH sub-expression “$()” to use get-date to generate a file name. I then format the file name with Year, Month, day, hour, minute, second. So a file name would be something like: C:\Transcripts\20151019103150.txt. Obviously you can choose whatever formatting you like.

After I’m logging my commands, the next thing I like to do is include the history number in my prompt along with the date (for the aforementioned transcript reviews that are almost certainly going to happen). Now, you can learn all about this with “help about_prompts” but again, these are my preferences).

So in that open notepad which contains the newly minted Transcript code, I will append the following lines for a little prompt-ly spice.

function prompt {
write-host "$(get-date -format s)" -ForegroundColor DarkGray -NoNewline
Write-Host "[h:$((get-history | measure).count)]" -ForegroundColor Yellow -NoNewline
Write-Host "$($executioncontext.sessionstate.path.currentlocation)$('>' * ($NestedPromptLevel + 1))" -ForegroundColor Green -NoNewline
" "

Again line by line:

  1. The prompt is defined by a function named ‘prompt’ so we’re redefining that
  2. I want the date and time printed first (handy for log files!) with a color of Yellow and without a newline
  3. I want my current history number[2] listed with a foreground color of Yellow
  4. I want my current location printed in green. I also want to know how many sessions deep I am (will come back to that in a minute).
  5. A string with a space. This is because PowerShell appends a “PS>” if prompt does not return a String.
  6. Close out the function

So – where are we now?  Let’s compare the original PowerShell experience with a new one.




NewPromptCheck out the nice colors of the prompt along with that “Transcript started” business on the fourth line.

Great! – now let’s install PsGet[3]. This is the PowerShell module repository tool to snag new modules from their directory. You can follow the instructions in the link at [3] or simply type:

(new-object Net.WebClient).DownloadString("<a href="http://psget.net/GetPsGet.ps1" rel="nofollow">http://psget.net/GetPsGet.ps1</a>") | iex

(NB: You might need to ‘Set-ExecutionPolicy RemoteSigned’ to make the above command work)

So we’re at the final steps for a good base config. Let’s add just one more thing. The very awesome PSReadLine module – which you can read all about at [3]. But if for no other reason, the sweet syntax highlighting is worth the trip!  To install, type:

Install-Module psreadline


Notice the difference in the two commands in the following screenshot… one highlights the command and the parameter. Beautiful!  Also note, that module has a ton of great features which should be thoroughly explored by the reader.

If you’re a developer using mercurial (hg), git, or possibly others, I’d encourage you to install some additional modules from the PSGet repository – they’ll make your life much easier. However, since not everone is – I will omit those from this post.

Happy PowerShelling!



[1]: There are four profiles that can be used. The default (represented by “$profile”) points to the “CurrentUserCurrentHost” profile. See ‘help about_profiles’

[2] “help get-history”

[3] https://github.com/lzybkr/PSReadLine/


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s