How to Get the Current Function Name in PowerShell

To get the current function name in PowerShell, read $MyInvocation.MyCommand.Name inside the function. It returns the name of the command that’s running right now:

function Get-OrderTotal { $MyInvocation.MyCommand.Name }   # Get-OrderTotal

I’ll also cover script blocks, the caller’s name, aliases, script paths, logging, and two PowerShell 7 vs 5.1 differences.

Get the current function name with $MyInvocation.MyCommand.Name

$MyInvocation is an automatic variable that PowerShell fills for every script, function, and script block. Its MyCommand property describes the command itself:

function Get-OrderTotal {
    $name = $MyInvocation.MyCommand.Name
    "Running $name for order 1042"
}
Get-OrderTotal

Output:

Running Get-OrderTotal for order 1042

The name isn’t hard-coded, so you can rename the function or copy the line into other PowerShell functions and the message stays correct.

Why the name changes in a script, function, or script block

$MyInvocation always describes the nearest command, so the same line returns different values depending on where it runs. I saved this as context.ps1 and ran it:

function Get-InvoiceStatus {
    'Function:     ' + $MyInvocation.MyCommand.Name
}
Get-InvoiceStatus
'Script:       ' + $MyInvocation.MyCommand.Name
& { 'Script block: [' + $MyInvocation.MyCommand.Name + ']' }
'Command type: ' + $MyInvocation.MyCommand.CommandType

Output:

Function:     Get-InvoiceStatus
Script:       context.ps1
Script block: []
Command type: ExternalScript
PowerShell 7 $MyInvocation.MyCommand.Name returns the function name, the script file name, and an empty script block name
$MyInvocation.MyCommand.Name inside a function, a script, and a script block (PowerShell 7)

Inside the function it’s the function name, sent to the pipeline like any of the return values of a PowerShell function. At the script level it’s the file name, with a CommandType of ExternalScript.

An anonymous script block has no name, so you get an empty string.

Use $PSCmdlet.MyInvocation in advanced functions

An advanced function (one with [CmdletBinding()]) also gets $PSCmdlet, which has its own MyInvocation property. It points to the same command, so it’s handy in Write-Verbose messages:

function Set-ShippingRate {
    [CmdletBinding()]
    param([string]$State = 'TX')
    $name = $PSCmdlet.MyInvocation.MyCommand.Name
    Write-Verbose "$name started for $State"
    "$name set the rate for $State"
}
Set-ShippingRate -State CO -Verbose

Output:

VERBOSE: Set-ShippingRate started for CO
Set-ShippingRate set the rate for CO

The VERBOSE line only shows up because I passed -Verbose, which works like any switch parameter in PowerShell. Without it, you’d only see the second line.

How do I get the calling function name in PowerShell?

$MyInvocation only knows about the current command. To find out who called it, use Get-PSCallStack: index 0 is the current function, and index 1 is its caller:

function Get-CallerName {
    $stack = Get-PSCallStack
    '{0} was called by {1}' -f $stack[0].FunctionName, $stack[1].FunctionName
}
function Update-Inventory { Get-CallerName }
function Start-NightlyJob { Update-Inventory }

Start-NightlyJob
Get-CallerName
'---'
function Show-Stack {
    Get-PSCallStack | Select-Object -First 3 |
        ForEach-Object { '{0,-18} line {1}' -f $_.FunctionName, $_.ScriptLineNumber }
}
function Invoke-Payroll { Show-Stack }
Invoke-Payroll

Output:

Get-CallerName was called by Update-Inventory
Get-CallerName was called by <ScriptBlock>
---
Show-Stack         line 12
Invoke-Payroll     line 15
<ScriptBlock>      line 16
Windows PowerShell 5.1 Get-PSCallStack shows the current function name and the calling function name
Get-PSCallStack returns the current function and its caller (Windows PowerShell 5.1)

When the script calls the function directly, the caller is <ScriptBlock>, the top level of the file. Frames after that belong to whatever started the script and change with how you run it, so I kept the first three. Both shells printed the same stack.

The same frames appear in $_.ScriptStackTrace when you handle errors with try and catch, which helps when an error comes from deep inside nested functions.

InvocationName vs MyCommand.Name with aliases

$MyInvocation.InvocationName is the name the caller typed, while MyCommand.Name is the real function name. The difference shows up with aliases and the call operator:

function Get-CustomerReport {
    'Called as {0,-20} real name {1}' -f $MyInvocation.InvocationName, $MyInvocation.MyCommand.Name
}
Set-Alias -Name gcrep -Value Get-CustomerReport
Get-CustomerReport
gcrep
& (Get-Command Get-CustomerReport)

Output:

Called as Get-CustomerReport   real name Get-CustomerReport
Called as gcrep                real name Get-CustomerReport
Called as &                    real name Get-CustomerReport

Use MyCommand.Name for logs, since it never changes. InvocationName helps when a function should act differently per alias.

Get the current script name and path

For the script itself, use $PSCommandPath for the full path and $PSScriptRoot for the folder. Inside a function, $MyInvocation.MyCommand.Path is empty because MyCommand is the function:

function Show-ScriptInfo {
    'PSCommandPath:  ' + $PSCommandPath
    'ScriptName:     ' + $MyInvocation.ScriptName
    'MyCommand.Path: [' + $MyInvocation.MyCommand.Path + ']'
}
Show-ScriptInfo
'Script path:    ' + $MyInvocation.MyCommand.Path
'Script folder:  ' + $PSScriptRoot
'File name:      ' + (Split-Path -Path $PSCommandPath -Leaf)

Output:

PSCommandPath:  C:\psfaqs\paths.ps1
ScriptName:     C:\psfaqs\paths.ps1
MyCommand.Path: []
Script path:    C:\psfaqs\paths.ps1
Script folder:  C:\psfaqs
File name:      paths.ps1

Inside the function, $MyInvocation.Script