Skip to content
Menu
The Lonely Administrator
  • PowerShell Tips & Tricks
  • Books & Training
  • Essential PowerShell Learning Resources
  • Privacy Policy
  • About Me
The Lonely Administrator

Measuring PowerShell Profile Performance

Posted on November 25, 2020November 25, 2020

Today's topic is one of those things that I don't know why I've never addressed before. Well, I have for myself in a manual process. Hopefully you'll find it useful.

Manage and Report Active Directory, Exchange and Microsoft 365 with
ManageEngine ADManager Plus - Download Free Trial

Exclusive offer on ADManager Plus for US and UK regions. Claim now!

As you probably know, PowerShell uses a set of profile scripts. These scripts have hard-coded paths and PowerShell runs them in order from broadest to narrowest.

  • All Users All Hosts
  • All Users Current Host
  • Current User All Hosts
  • Current User Current Host

The host refers to the PowerShell host that you see when you look at $host. The $profile variable shows you the value for current user current host script. But you can easily see all the values.

Here's the "issue" that often arises. Someone will mention that PowerShell, and this includes PowerShell Core, takes too long to load. In fact, PowerShell now shows you how long it took to load. Almost always, the issue is something profile related. Sometimes a command is taking too long to run, or maybe the profile needs a little cleanup. I know my PS7 load times were high until I cleaned up a few items and re-structured some of the commands.

To make this easier, I put together a simple script that you can run in Windows PowerShell, or PowerShell (even cross-platform) that will run your profile scripts and report how long they take to complete.

#requires -version 5.1

#test profile script performance

<#
C:\scripts\Test-ProfilePerf.ps1
C:\scripts\Test-ProfilePerf.ps1 -outvariable p | measure-object -Property TimeMS -sum
$p

#>

[cmdletbinding()]
Param()

#this is the scriptblock of commands to run in a new Powershell/pwsh session
$sb = {
    $profiles = [ordered]@{
        AllUsersAllHosts       = $profile.AllUsersAllHosts
        AllUsersCurrentHost    = $profile.AllUsersCurrentHost
        CurrentUserAllHosts    = $profile.CurrentUserAllHosts
        CurrentUserCurrentHost = $profile.CurrentUserCurrentHost
    }

    #only need to get these values once
    $psver = $PSVersionTable.PSVersion
    $computer = [System.Environment]::MachineName
    $user = "$([System.Environment]::UserDomainName)\$([system.Environment]::userName)"

    foreach ($prof in $profiles.GetEnumerator()) {
        If (Test-Path $prof.value) {
            # Write-Host "Measuring script for $($prof.key)" -ForegroundColor cyan
            $m = Measure-Command { . $prof.value }

            #create a result
            [pscustomobject]@{
                Computername = $computer
                Username     = $user
                PSVersion    = $psver
                Profile      = $prof.key
                Path         = $prof.value
                TimeMS       = $m.totalMilliseconds
            }
        } #if test path

    } #foreach profile
} #scriptblock

#use the detected PowerShell version
if ($PSEdition -eq 'Core') {
    #Windows uses pwsh.exe and non-Windows uses pwsh. 
    $cmd = (Get-Command pwsh).source
    $result = &$cmd -nologo -noprofile -command $sb
}
else {
    $result = powershell.exe -nologo -noprofile -command $sb
}

#use $result as the output of this command
$result

The script file runs a scriptblock in a new PowerShell or pwsh session with no profiles. The scriptblock runs each profile script in order and measures how long each detected profile script runs. The performance times should be pretty close.

If you'd like to see a total you could run a command like:

C:\scripts\Test-ProfilePerf.ps1 -outvariable p | measure-object -Property TimeMS -sum

The script is configured with cmdletbinding so you can use a common parameter like OutVariable.

If you test, and one of the scripts seems to take a long time, wait a minute and repeat the test. If you consistently get a value you don't like, at least now you have something to investigate.

Caveats

This script makes an assumption that your profile scripts aren't taking drastic steps like creating new Active Directory users or deleting files. I'm assuming you are using a profile script to define things like variables and PSDrives, and import modules or define functions.

This version of the script also won't test profile scripts under hosts such as VS Code or the PowerShell ISE.

I hope you find this helpful.


Behind the PowerShell Pipeline

Share this:

  • Click to share on X (Opens in new window) X
  • Click to share on Facebook (Opens in new window) Facebook
  • Click to share on Mastodon (Opens in new window) Mastodon
  • Click to share on LinkedIn (Opens in new window) LinkedIn
  • Click to share on Pocket (Opens in new window) Pocket
  • Click to share on Reddit (Opens in new window) Reddit
  • Click to print (Opens in new window) Print
  • Click to email a link to a friend (Opens in new window) Email

Like this:

Like Loading...

Related

reports

Powered by Buttondown.

Join me on Mastodon

The PowerShell Practice Primer
Learn PowerShell in a Month of Lunches Fourth edition


Get More PowerShell Books

Other Online Content

github



PluralSightAuthor

Active Directory ADSI Automation Backup Books CIM CLI conferences console Friday Fun FridayFun Function functions Get-WMIObject GitHub hashtable HTML Hyper-V Iron Scripter ISE Measure-Object module modules MrRoboto new-object objects Out-Gridview Pipeline PowerShell PowerShell ISE Profile prompt Registry Regular Expressions remoting SAPIEN ScriptBlock Scripting Techmentor Training VBScript WMI WPF Write-Host xml

©2025 The Lonely Administrator | Powered by SuperbThemes!
%d