Sunday, 22 May 2011

Own Your Powershell Profile

I have not blogged in quite a while but I think it is worth giving powershell a mention.  I think that a lot of windows developers are missing a trick by first of all not using powershell and secondly by not customising their powershell profile.  

Like a lot of windows developers, I had never really seen the need for powershell and I had written it off without even trying it.  I happily fumbled about with DOS and batch files.  That is until I bought a Mac Book air and decided that the bash shell was a much more agreeable experience compared to messing about with the  Mac windows explorer equivalent called finder.  I was instantly struck how much more efficient using the terminal (command prompt in windows speak) is than messing about with windows.  The obvious advantage being that you can create reusable scripts of the recurring actions you frequently execute during the course of your terminal session.  In bash you can configure your shell by placing customisation commands in 1 of 3 system configuration files, the one I used most was the .bashrc file that is processed every time you open a non-login shell.  One of the most productive customisations that I discovered was the ability to set up typing short cuts or aliases.

Once I returned to windows, I found myself loathe to use windows explorer, filezilla and other graphical user interfaces. I was struck by how inefficient they were and how I was repeating the same actions over and over again.  The whole point of programming is to automate repeating tasks.  I then turned to powershell and I was delighted to discover that powershell has the concept of the powershell profile which is analogous to the .bashrc file in that it is processed every time you open a powershell shell command prompt.  

Your Divine Right To Customise Your Shell

The first task that you that you need to accomplish, that is if you have yet to customise your profile is to find the damn thing. Luckily powershell holds the location in a built in global variable that you can access by typing $PROFILE at  your powershell command prompt:

PS> $PROFILE                                                                                                                                                                                         

$PROFILE returns the full path of the file that powershell will try to run when it starts
PS> C:\users\paul.cowan\Documents\windowsPowerShell\Microsof.Powershell_profile.ps1                                            

Strangely, the file is not created for you by default.   You can of course use powershell to test for its existence using the Test-Path cmdlet:

PS> Test-Path $profile                                                                                                                                                                

If your profile does not exist, you need to create it (obviously) and the New-Item cmdlet will enable you to achieve this

PS> New-Item  -path $profile -type -file -force                                                                                                                           

Once you have created the $profile, you can set to work customising it by opening the file in notepad:

PS> notepad $profile                                                                                                                                                                   


I mentioned aliases at the start of this post and this is where we can start to add typing shortcuts to drastically speed up our workflow.  We can for example add an alias that will open up our favourite text editor. This is accomplished with the set-alias cmdlet:

  1. set-alias npp "C:\Program Files (x86)\Notepad++\notepad++.exe"

If we type the above entry into our powershell profile file (Microsoft.PowerShell_profile.ps1) and then try to run the new command by entering npp into an existing powershell command prompt, we will get an error along the lines of

The term 'npp' is not recognised as the name of a cmdlet, function or operable program.

This is because the profile is only processed at the beginning of each new powershell prompt session.  We can though reload the profile using the dot source syntax below or by opening a new powershell command prompt:

PS> . $PROFILE                                                                                                                                                                            

Now if we type npp into the prompt, the notepad++ executable will start.


Being able to add your own functions to your powershell profile and have them available for every powershell session is insanely useful.  This is best illustrated with a very simple example.  I have a number of functions and aliases that let me teleport from location to location on the file system.  The below example will cd into my projects directory:

  1. function pr
  2. {
  3.     set-location C:\projects\ 
  4. }

PS> pr                                                                                                                                                                                                                                                                                                           

Two keystrokes will get me where I want to go.  You really need to contrast this puerile example with the same actions in windows explorer.

This is ridiculously simple but I have lots of these simple location changers that zip me about from place to place.

Below is a powershell function that I use constantly when finding files:

  1. function ff ([string] $glob)
  2. {
  3.     get-childitem -recurse -include $glob
  4. }

If I want to recursively find all text files in a directory hive, I can simply type the following into the prompt:

PS> ff *.txt                                                                                                                                                                                         

Once you start adding these customisations, you will find yourself constantly tweaking your workflow.

Combining Functions and Aliases

The following example shows how I can create a powershell remote session on another server.  I am not going to get into the syntax here but I might blog about remote powershell sessions in another post which at this rate will be in another year.  The point of this example is to show how I can create the session with 2 key strokes.  First of all is the function to create the session:

  1. function New-PSSecureRemoteSession
  2. {
  3.     param ($sshServerName, $Cred)
  4.     $Session = New-PSSession $sshServerName -UseSSL -Credential $Cred -ConfigurationName C2Remote
  5.     Enter-PSSession -Session $Session
  6. }

I then set an alias to the function:

  1. set-alias sh New-PSRemoteSession

Two keystrokes and I have a new session on the server.  I hope this illustrates what is truly possible as you become more comfortable.  I was inspired to look for the ability to execute remote powershell commands after having this ability with ssh on unix and linux.  I would never have even considered this if I had not looked into other platforms which really is the moral of this story.  You should always look to other platforms to bring ingenuity into your own.

The Icing on the cake

As you build up your profile over time, it becomes indispensable.  You want to have it with you at all times.  I keep mine in git and I can simply clone it onto any new machine that I am working on.  You could also use dropbox.

I think I read in the Pragmatic Programmer that you should know your shell and as usual, this is sound advice.

Here is a link to my entire profile.


  1. Nice article - I am just back from a week manning the PowerShell booth at TechEd. There certainly is some confusion over profiles.

    A couple of points: strictly speaking, $PROFILE is one of 4 profiles you can have/use and the file pointed to by this variable differs between Powershell.exe and ISE. Also, the $Profile files are intentionally NOT created for security reasons, but creating them is trivial.

  2. Thanks for this. One minor typo though - the command should be:
    New-Item -path $profile -type file -force