Supercharging your PowerShell Profile

ise $profile; Remember this command

One of the things that would separate a true ninja of the PowerShell world from a mere dabbler may be the intelligent use of Powershell’s Profile features to save work.

After all, the whole point of an automation language like PowerShell is to cut down on unnecessary work. I mean, who wants to type Import-Module a hundred times a week when they can type ipmo?

Indeed, who needs to type ipmo at all? And if you use your profiles smartly, you don’t have to.

Here, for instance, is how my Powershell window looks when I fire it up right now.


So, let’s look into what goes on under the covers there.

First of all, let’s just explain how profiles work. Fire up a PowerShell window and type this

Get-Help About_Profiles

OK, it’s a bit wordy, but here’s the basic deal. Your PowerShell profiles allow you to customise your PowerShell environment in pretty much any way you want. There are four of them.

First, $Profile – current user, current host. This is the profile that will run when you fire up a new session on the current powershell host as your current identity. It’s also known as $profile.CurrentUserCurrentHost

Then there are three others

  • CurrentUserAllHosts – the current user account, and all powershell hosts
  • AllUsersCurrentHost – anyone on this machine, in the current powershell host
  • AllUsersAllHosts – anyone on this machine, in any powershell host

Huh? All users/current user should be pretty obvious. But the other one perhaps less so. The main difference is this. If you run the PowerShell ISE and type


you’ll be viewing a different path than if you ran the standard powershell prompt and typed the same thing. Try it out. You see, the Integrated Scripting Environment has its own profile, allowing you to customise only what gets loaded in the ISE. Hence, four different profiles.



One last thing – a newly setup machine might not have the profile you’re looking for. So you might have to run this little one-liner to check if it’s there, and if it’s not, create it

if(!(Test-Path $profile.CurrentUserAllHosts)) {New-Item $profile.CurrentUserAllHosts -ItemType file -force}

Now, I don’t care about a specific profile for the ISE, and I’m the only user on the box that needs this custom profile, so I edit my $profile.CurrentUserAllHosts, aka


And what goes on in there? Well, let’s take another look at my PowerShell window.


Fairly easy to follow, this one. First of all, we check the powershell version currently running, and we load a couple of modules. Here’s the code that does that

Write-Host -ForegroundColor Cyan "You are running Powershell version" $PSVersionTable.PSVersion

# Guy Garvie
Write-Host "Loading GuyGarvie"
ipmo C:\GuyGarvie\Start-PageWarmUp.ps1
Write-Host "Loading Son of Guy Garvie"
ipmo $home\Scripts\SonOfGuyGarvie\SonOfGuyGarvie.ps1
#F5 control script
Write-Host "Loading F5 LB control script"
ipmo C:\Scripts\F5LB\F5.ps1

Pretty simple. A Write-Host call using $PSVersionTable.PSVersion so I know what version I’m on at a glance. Then I load three modules.

  • GuyGarvie is a website warmup script which grabs a site map off disk and hits the pages sequentially to warm up the .NET runtime. He’ll be the topic of a later post.
  • SonOfGuyGarvie is an enhanced version of the same, which grabs the sitemap from a central location and does the warmup asyncronously, eight pages at a time
  • F5.ps1 is some script for the F5 iControl interface, which allows me to control nodes in our Load Balancer

So there are three Import-Module calls – all from different places – that I never have to do again, at least on this machine. So far so good. Then there’s something about xWebAdministration, which is a DSC provider for IIS. I do a fair bit of work with IIS, so this is an important one to have loaded in the ISE. I can then write idempotent configuration scripts for new environments with minimal hassle. I load that with the following snippet

if((gmo -Listavailable | ? { $ -like "*xwebadministration*"})) {
    Write-Host "xWebAdministration is installed"
    Write-Host "xWebAdministration is not available, installing"
    $modpath = (Join-Path -Path $home -ChildPath documents\windowsPowerShell\Modules)
    if(!(Test-Path $modpath)){mkdir $modpath}
    iwr -OutFile $env:TEMP\
    Expand-Archive -Path $env:TEMP\ -OutputPath $modpath
ipmo xWebAdministration

This one is a bit more advanced than the other module loads. This is partly because it came later and partly because this snippet was written in order to get the module installed onto newly provisioned servers. It checks if xWebAdministration is available, and if it’s not, installs it. If it is available, however, it does nothing except tell me so, and then at the end, it imports the module.

Then the last bit. The bit in yellow. Evil me oh yeah I know. What’s all that about?

Well, that’s a random line from one of my favourite songs, Bukowski by Modest Mouse. I wrote it as a more interesting “Hello World” for a PowerShell workshop – inspired by WordPress’s Hello Dolly Plugin – and I liked it so much I kept it.

Here’s how it works

$line = (Get-Content $home\Bukowski.txt | Get-Random) 
Write-Host -ForegroundColor Yellow $line

So with this little intro, you can probably imagine some other cool ways a profile could be used to rev up your PowerShell environment. You can load modules, call web services, get updates, check the status of your servers, tell yourself the current time in Irkutsk or – and this one is a pretty cool idea – send a request to your home automation server to turn up the stereo and change the room’s lighting to something a bit more appropriate.

Better still, you can host a version of your profile somewhere out on the web – behind a password, naturally – and when you stand up a new machine, you can run something like this

iwr -uri -outfile $profile

And suddenly all your favourite add-ins, modules, song lyrics and light settings are there, ready for you to use, any time you need them

And you thought PowerShell was just a fancy command-line. That’ll teach you.


Leave a Reply

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