AbraCadaver
AbraCadaver

Reputation: 78994

Get original script name included script name and possibly others

I've been testing $MyInvocation, $MyCommand and inspecting some other variables but would like a good example of how to do the following:

  1. Get the name of the current script file
  2. Get the name of the caller script file that included the current script file
  3. Get the name of the original script file that ultimately resulted in #1 being executed

I have used this for original but maybe it will also be caller?

$myInvocation.MyCommand.Name #original

Even if there are more files involved, I only need the current, caller and original. Consider three scripts; if you were to execute first.ps1:

first.ps1

    . "$PSScriptRoot\second.ps1"

second.ps1

    . "$PSScriptRoot\third.ps1"
    #get $Current  = second.ps1
    #get $Caller   = first.ps1 
    #get $Original = first.ps1

third.ps1

    #get $Current  = third.ps1
    #get $Caller   = second.ps1 
    #get $Original = first.ps1

I have worked out how to get the filename from the path etc...

Also, why is syntax highlighting wonky on SO for PowerShell?

Upvotes: 2

Views: 1414

Answers (1)

mklement0
mklement0

Reputation: 438263

Place the following in second.ps1 and third.ps1, which utilizes the automatic $PSCommandPath variable and Get-PSCallStack:

# Get the full paths of the scripts on the call stack (the calling scripts).
$callingScripts = (Get-PSCallStack).InvocationInfo.PSCommandPath -ne $null

# For illustration, use a custom object to show the current script's 
# file name, that of the immediate caller, and that of the original caller.
[pscustomobject] @{
  Current = Split-Path -Leaf $PSCommandPath
  Caller = Split-Path -Leaf $callingScripts[0]
  Original = Split-Path -Leaf $callingScripts[-1]
}

Your third.ps1 script would then output the following:

Current   Caller     Original
-------   ------     --------
third.ps1 second.ps1 first.ps1

Explanation:

  • The automatic $PSCommandPath variable contains the running script's own full file-system path.

  • Get-PSCallStack outputs the call stack in the form of System.Management.Automation.CallStackFrame instances, bottom-up: that is, the instance at index 0 represents the immediate caller, whereas index -1 - the last array element - represents the top of the call stack and therefore the original caller.

  • .InvocationInfo.PSCommandPath is an instance of member-access enumeration, which extracts the caller script path's across all stack frames (across all array elements).

    • Non-script-file callers may be involved as well, notably the initial script block used behind the scenes to submit a command from the interactive prompt, and the .PSCommandPath property of such contains $null.
    • -ne $null is used to filter out these $null values, so that the array returned contains only the paths of script-file callers.
  • Split-Path -Leaf is used to extract just the file-name portion from the full paths.


why is syntax highlighting wonky on SO for PowerShell?

Good question. It seems that some heuristic is being implied to guess the language, and it frequently guesses wrong; As of this writing, explicitly specifying ```powershell at the start of a fenced code block doesn't help, suggesting that PowerShell isn't a supported language. For now, ```sh, even though it's the wrong language, works reasonably well in practice.

Upvotes: 5

Related Questions