Monday, March 10, 2008

Custom PowerShell prompt


If you are used to measuring commands in PowerShell then this custom prompt can be useful for you. Instead of measuring commands manually (with measure-command), the custom prompt code (below, comments inline) automates the measuring process and presents three bits of information at the console title. Here is how it looks:



  1. The first part (c:\scripts) shows the current working directory.
  2. The second part (Session Execution Time: 00:12:15) displays, in HH:mm:ss format, the total amount of time it took PowerShell to execute all commands since the console had started.
  3. The last part (Last [00:01.546]) displays how long it took the last command to be completed, in mm:ss.millisecond format.

The last part of the prompt (PS 3>) shows the ID of the last executed command, you ca use the ID to invoke commands, instead of retyping them, from the commands history by passing the command ID, see the help for get-history.

To use the prompt, copy the code below and paste it into your $profile, restart PowerShell and type some commands, you'll see the console title changes.


***UPDATE # 1 ***
Already found a bug. Repeatedly pressing the ENTER key causes the global $pshUse to add-up the last command execution time. The code below includes the fix.

***UPDATE # 2 ***

Added support for $NestedPromptLevel visualization. Thanks Andy!
Each nested prompt level is indicated by an extra ">"


# global variable to hold total (cumulative) execution time
$global:pshUse = New-TimeSpan
# holds the last command id
function Prompt{ 
    # get the last command
    $item = Get-History -Count 1
    # don't add-up times when typing ENTER repeatedly
    if($global:lasdID -ne ${
        # get the last command execution time (timespan)
        $diff = $item.EndExecutionTime-$item.StartExecutionTime
        # add it to the global $pshUse
        $global:pshUse = $global:pshUse.Add($diff)
        # string format total execution time in HH:mm:ss 
        # and last command execution time in mm:ss.milliseconds    
        $title = "{0:T} , Last [{1:mm:ss.fff}]" -f [datetime]($pshUse.ticks),[datetime]($diff.ticks)
        # update console title, show current directory, 
        # session execution time, and last command execution time
        $host.UI.RawUI.WindowTitle = "{0} | Session Execution Time: {1}" -f $pwd,$title
    # write custom prompt with the last history command id 
    # each nested prompt level is indicated by an extra ">" 
    "PS {0}{1} " -f $, (">"*($NestedPromptLevel+1))




Anonymous said...

This is some great and very useful information. One quick note that I actually just blogged about the other day:

When you are using custom prompts, you want to be sure to account for $nestedpromptlevel so you can see when you are in a nested/suspended prompt.

Shay Levy said...

Thanks Andy! I updated the post.