A Comprehensive Guide to Getting the Current PowerShell Script Path: From Basics to Advanced Practices

Dec 03, 2025 · Programming · 9 views · 7.8

Keywords: PowerShell | script path | compatibility | $PSCommandPath | $MyInvocation

Abstract: This article delves into various methods for obtaining the path of the currently executing PowerShell script, focusing on the behavioral differences of key variables such as $PSCommandPath, $MyInvocation.ScriptName, $MyInvocation.MyCommand.Name, and $MyInvocation.MyCommand.Definition. Through detailed code examples and scenario testing, it reveals compatibility issues across different PowerShell versions (particularly 1.0 to 5.0) and provides practical backward-compatible solutions. The article also discusses special cases for retrieving script paths within functions and techniques for extracting filenames rather than full paths, offering comprehensive references for developers handling script path issues in real-world projects.

Introduction and Problem Context

In PowerShell script development, obtaining the path of the currently executing script is a common yet nuanced requirement. For instance, when launching a script via powershell.exe .\myfile.ps1, developers might want to retrieve path information like \"myfile.ps1\" or \".\\myfile.ps1\". This issue is particularly complex in early versions like PowerShell 1.0 due to the lack of a unified solution.

Core Methods and Variable Analysis

PowerShell provides several automatic variables to access script information, but their behavior varies by context and version. The most commonly used variables include:

$PSCommandPath Variable

This is the recommended method in PowerShell 3.0 and later. $PSCommandPath directly returns the full path of the currently executing script, regardless of whether it's called inside a function. For example:

# Example: Direct use of $PSCommandPath
Write-Host \"Script path: \" $PSCommandPath
# Output: C:\\Test\\test.ps1

However, this variable does not exist in versions prior to PowerShell 3.0, requiring compatibility handling.

$MyInvocation-Related Variables

For older PowerShell versions, the $MyInvocation object offers multiple properties with complex behaviors:

Compatibility Solutions

To use $PSCommandPath in versions before PowerShell 3.0, a shim code can be inserted:

if ($PSCommandPath -eq $null) {
    function GetPSCommandPath() {
        return $MyInvocation.PSCommandPath;
    }
    $PSCommandPath = GetPSCommandPath
}

This code checks if $PSCommandPath exists and assigns it via a function if not. Note variable scoping rules: if the shim is placed inside a function, the variable is limited to that function.

Detailed Testing and Comparison

To fully understand these variables' behaviors, we designed a test script:

function PSCommandPath() { return $PSCommandPath }
function ScriptName() { return $MyInvocation.ScriptName }
function MyCommandName() { return $MyInvocation.MyCommand.Name }
function MyCommandDefinition() {
    # Note: This function returns the definition content, not execution results
    return $MyInvocation.MyCommand.Definition
}
function MyInvocationPSCommandPath() { return $MyInvocation.PSCommandPath }

Write-Host \"\"
Write-Host \"PSVersion: \" $($PSVersionTable.PSVersion)
Write-Host \"\"
Write-Host \"`$PSCommandPath:\"
Write-Host \" *   Direct: \" $PSCommandPath
Write-Host \" * Function: \" $(PSCommandPath)
Write-Host \"\"
Write-Host \"`$MyInvocation.ScriptName:\"
Write-Host \" *   Direct: \" $($MyInvocation.ScriptName)
Write-Host \" * Function: \" $(ScriptName)
Write-Host \"\"
Write-Host \"`$MyInvocation.MyCommand.Name:\"
Write-Host \" *   Direct: \" $($MyInvocation.MyCommand.Name)
Write-Host \" * Function: \" $(MyCommandName)
Write-Host \"\"
Write-Host \"`$MyInvocation.MyCommand.Definition:\"
Write-Host \" *   Direct: \" $($MyInvocation.MyCommand.Definition)
Write-Host \" * Function: \" $(MyCommandDefinition)
Write-Host \"\"
Write-Host \"`$MyInvocation.PSCommandPath:\"
Write-Host \" *   Direct: \" $($MyInvocation.PSCommandPath)
Write-Host \" * Function: \" $(MyInvocationPSCommandPath)
Write-Host \"\"

Example output when executing C:\\Test\\test.ps1 in PowerShell 5.1:

PSVersion: 5.1.19035.1

$PSCommandPath:
 *   Direct: C:\\Test\\test.ps1
 * Function: C:\\Test\\test.ps1

$MyInvocation.ScriptName:
 *   Direct:
 * Function: C:\\Test\\test.ps1

$MyInvocation.MyCommand.Name:
 *   Direct: test.ps1
 * Function: MyCommandName

$MyInvocation.MyCommand.Definition:
 *   Direct: C:\\Test\\test.ps1
 * Function:
    # Note: This function returns the definition content, not execution results
    return $MyInvocation.MyCommand.Definition;

$MyInvocation.PSCommandPath:
 *   Direct:
 * Function: C:\\Test\\test.ps1

Key observations:

Advanced Scenarios and Supplementary Techniques

Based on supplementary answers, note the following cases:

Retrieving Script Name Inside Functions

Inside a function, $MyInvocation.MyCommand.Name returns the function name, not the script name:

function test {
    $MyInvocation.MyCommand.Name  # Returns \"test\", not the script filename
}

In this case, use $MyInvocation.ScriptName to get the script path.

Extracting Filename Without Full Path

If only the script filename (without path) is needed, use:

$ScriptName = $MyInvocation.MyCommand.Name  # Returns e.g., \"test.ps1\"

Or combine with Split-Path:

Split-Path $MyInvocation.PSCommandPath -Leaf  # Extracts filename from path

Path Validation and Fallbacks

$MyInvocation.MyCommand.Definition typically returns a valid path but may not be the original user-input path. In complex scenarios, validate by combining multiple variables.

Summary and Best Practices

When obtaining the current PowerShell script path, recommend the following strategies:

  1. If targeting PowerShell 3.0 or later, use $PSCommandPath directly.
  2. For backward compatibility, insert shim code to emulate $PSCommandPath.
  3. Inside functions, prefer $MyInvocation.ScriptName for script paths.
  4. For filenames only, use $MyInvocation.MyCommand.Name or Split-Path -Leaf.
  5. Always test code behavior in target PowerShell versions to avoid assumptions.

By understanding these variables' nuances and version differences, developers can write more robust and portable PowerShell scripts.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.