Pimp your Powershell - Create a profile

First of all Happy Eastern to everyone! We got some day off because of it so we can dive deeper into a powershell customization project. Let’s see, how can we increase thr comfort factor using powershell (referred to as pshell) by tailor our profile. happy_eastern

Table of content

What profile do

The profile in pshell can be very handy in many situation, for example

  • Declare variables to your session
  • Load modules
  • Start logging automatic
  • Whatever you want

So the profile is a script, that runs each time, when the pshell console starts.

Check your Execution Policy

Before you can change anything related your profile, you ought to check, which execution policy is set in your machine.

After start, type


command, the returned string is ‘Restricted’ by great chance. That means we cannot run script inside the shell (I’ll write a workaround in a later post ), so we must change it before start create a profile. In nutshell there 5+1 kind of these policies, from the strictest to the lenient: Restricted -> AllSigned -> RemoteSigned -> ByPass -> Unrestricted | +1 Undefined If you want to read about this policies, check the official site.

In order to change the policy you should start a pshell console as administrator windows+X then select Windows Powershell (Admin) then start typing

Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy Bypass

To check the settings, type again After start, type


The -Scope switch can be omitted, if you want to set the policy for all user, or you can simplify the command to

Set-ExecutionPolicy Bypass

I prefer the verbose mode, it helps a lot later, when you check your scripts.

Blueprint of your profile script

First, find where does live the profile with type $profile It will be the C:\Users\undergrinder\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1 path, if we customize first time, this file doesn’t exist. Type notepad $profile and click yes, if you are asked to create this file in the opened notepad.

I hope your real private directory is not the same with the deafult windows user directory, so we will dot source an other profile file in the official $profile file. This step can be omitted, and write your code here, I prefer dot sourcing other file. . D:\undergrinder\real_profile.ps1 Type notepad D:\undergrinder\real_profile.ps1, or just create it and open with your favorite text editor (mine is Notepad++), and type in the first line Write-Host 'It WORKS!!!!!' `n -foregroundcolor 'darkgreen'

When you restart pshell, this message should appear:

Start customizing


I like to see my pshell greet me, so our first line should be:

Write-Host 'Hey undergrinder!' `n -foregroundcolor darkgreen

Create our custom object, that makes the world (or at least your session) better!

Define an object with regularly used folders, files and so on… The limit is the sky (the limit is powershell’s capabilities…). This is just an example, feel free to expand/collapse the properties:

$tg = new-object psobject `
  -property  @{home        = "e:\undergrinder\home";
               desktop     = "c:\Users\undergrinder\Desktop";                      
               fav1        = "e:\myFavouriteDirectory1\";
               fav2        = "e:\myFavouriteDirectory2\";
               modules     = "e:\undergrinder\powershell\modules\";                                      
               scripts     = "e:\myFrequentlyUsedScripts\";
               bmode       = if([environment]::Is64BitProcess){64} else {32};
               startloc    = (Get-Location);
               transcripts = "e:\undergrinder\powershell\transcripts\";}

If we wonder what kind of session do we have just type after startup $tg.bmode, and we get 32 if we are in a 32bit session for example.

Inform us about the object

At startup we wants to see which values do we have in our own object, so we list it’s content.

Write-host -foregroundcolor 'gray' 'o Session object''s ($tg) elements':

Add modules

Besides the installed modules, we can add modules to the profile as well, I prefer this method in some cases, for example when you star pshell with -noprofile switch there are modules I don’t want to be loaded into that session. So we add administrate our modules into our own object:

$tg|Add-Member -NotePropertyName loaded_modules `
               -NotePropertyValue @()

We have just added a new property, an array, that will hold our module’s name. Use the basic Import-Module cmdlet to import your desired module, but don’t forget to assign it’s name to loaded_modules property.

$tg.loaded_modules += 'module1'

Check what function/cmdlets belongs to our profile

We expand our object again

$commands = get-command| `
            where-object{$_.source -in $tg.loaded_modules}
$tg|Add-Member -NotePropertyName commands `
               -NotePropertyValue $commands

Remember the [yourObject].loaded_modules is mostly for information purposes, but if we implement this feature we should pay attention to proper naming the modules, because of the Where-Object cmdlet.


It is a good idea store our alias in profile, it’s syntax is new-alias [alias name] [command name] so for example we add the following line to the script

new-alias gep get-executionpolicy


We can define folders to behave like drives. It’s also a good idea to move these commands in our profile. For example the default windows user directory can be a fancy drive.

New-PSDrive -Name "user" `
            -PSProvider "FileSystem" `
            -Root "c:\Users\undergrinder\"

Logging our session

Creating transcript is a handy method, I suggest everyone to include it in his/her profile. Transcript is a text file log about your session, it stores what commands did you use, and they’s outputs. Further information see the official site

First we create a variable, that holds the name of our transcript, and add to our object:

$sessionlog = $($tg.transcript      + `
                $env:userdomain +'-'+ `
                $env:username   +'-'+ `
                (get-date -f 'yyyyMMddHHmmss')+'.log')

$tg|Add-Member -NotePropertyName current_transcript `
               -NotePropertyValue $sessionlog                

Append the next line to to end of our profile file:

Start-Transcript $tg.sessionlog|out-null	

After the pipe out-null makes sure that we don’t get verbose message about starting the script.


Write-host `n'Have a nice session!' -foregroundcolor darkgreen 

With the `n literal we ensure, that our message will start in new line.

Add Lucy

write-host "                     ___.-'''-.          "
write-host "                    (  (___,/\ \         "
write-host "                     \(  |')' ) )        "
write-host "                      \)  \=_/  (        "
write-host "                ___   / _,'  \   )       "
write-host "              .'  \|-(.(_|_   ; (        "
write-host "             /   //.     (_\, |  )       "
write-host "   /`'---.._/   /.\_ ____..'| |_/        "
write-host "  | /`'-._     /  |         '_|          "
write-host "   `      `;-'';  |         /,'          "
write-host "            `'.__/         ( \           "
write-host "                           '\/           "
write-host "                                         "

Bring all together


I’ve just guided you through the secret of profile creation, I’m sure you have already come up with ideas, how can you expand your session. If you have thoughts to share with me, leave a comment below.

You find an example profile script at my GitHub page.