Get Notified When Long-Running Commands Finish in PowerShell 7
Source: Dev.to
How this works
When you press Enter, a timestamp is recorded. After the command finishes, the next prompt compares the current time with the stored timestamp. If the elapsed time exceeds the threshold, a toast notification is triggered using the BurntToast module.
Steps
Step 1 – Install the BurntToast module
Install-Module BurntToast
Step 2 – Find your PowerShell 7 profile path
$PROFILE
Typical output:
C:\Users\<UserName>\Documents\PowerShell\Microsoft.PowerShell_profile.ps1
Step 3 – Open the profile in your editor
code $PROFILE
(Use any editor you prefer.)
Step 4 – Import the module
Import-Module BurntToast
Note: This import should be at the top of the profile; otherwise the following code won’t work.
Step 5 – Add the notification logic
Paste the following at the top of your profile after the Import-Module line:
$OriginalPrompt = (Get-Command prompt).ScriptBlock # capture original prompt
# Notification needs a logo; we’ll use PowerShell’s icon
$applogo = "C:\Program Files\PowerShell\7\assets\Powershell_av_colors.png"
$ExecutionNotifyThreshold = 3 # seconds
$global:__commandStart = $null
function Format-Elapsed([TimeSpan]$timestamp) {
if ($timestamp.TotalSeconds -lt 60) {
return ('{0:0.0}s' -f $timestamp.TotalSeconds)
}
$parts = New-Object System.Collections.Generic.List[string]
if ($timestamp.Days -gt 0) { $parts.Add("{0}d" -f $timestamp.Days) }
if ($timestamp.Hours -gt 0) { $parts.Add("{0}h" -f $timestamp.Hours) }
if ($timestamp.Minutes -gt 0) { $parts.Add("{0}m" -f $timestamp.Minutes) }
$parts.Add("{0}s" -f $timestamp.Seconds)
return ($parts -join ' ')
}
function global:prompt {
if ($global:__commandStart) {
$elapsed = (Get-Date) - $global:__commandStart
if ($elapsed.TotalSeconds -ge $ExecutionNotifyThreshold) {
$lastCmd = (Get-History -Count 1).CommandLine
$text = @(
'PS7 Finished:'
"`$ $lastCmd"
("Took {0}" -f (Format-Elapsed $elapsed))
)
New-BurntToastNotification -Text $text -AppLogo $applogo
}
$global:__commandStart = $null
}
& $OriginalPrompt
}
Adjust $ExecutionNotifyThreshold (in seconds) to suit your needs.
Step 6 – Record the start time on Enter
Add this at the end of your profile so nothing overrides it:
Set-PSReadLineKeyHandler -Key Enter -ScriptBlock {
$global:__commandStart = Get-Date
[Microsoft.PowerShell.PSConsoleReadLine]::AcceptLine()
}
Save the file and either restart your shell or run:
. $PROFILE
Now run a command that takes longer than the threshold; you should see a toast similar to the one below:
Notes & Caveats
- This works fine with oh‑my‑posh, starship, or other prompt frameworks as long as you load the above code after the framework configures its prompt.
- It overrides the global
promptfunction. If you have another custom prompt, merge the logic accordingly. - The
Enterkey is hooked via PSReadLine. If you already have a customEnterhandler, combine the scripts.
Removing the behavior
If you decide you no longer want notifications, run:
Remove-PSReadLineKeyHandler -Key Enter
That’s it! You can now run long‑running commands without constantly watching the console. 🎉
