Warm tip: This article is reproduced from stackoverflow.com, please click
powershell

How do I get the name of the script file a Class is called from when it is nested in a dot source ca

发布于 2020-03-27 10:17:29

If I have the following (simplified Setup)

class.ps1

class Test {
    Test() {
        $MyInvocation | Show-Object
    }

    [void] Call() {
        $MyInvocation | Show-Object
        <# 
           here $MyInvocation.ScriptName, PSCommandPath show main.ps1 NOT 
           util.ps1 even though it is called from Util.ps1 
        #>
    }
}

Util.ps1

Write-Host "Calling from Util.ps1"
$MyInvocation | Show-Object

Function Test-Util {
    [CmdletBinding()]
    Param()

    Write-Host "Calling from Test-Util in Util.ps1"
    $MyInvocation | Show-Object
}

Function Test-Class {
    [CmdletBinding()]
    Param()

    write-host "Testing Class Test from Util.ps1"
    $Test = [Test]::new()
    Write-Host "Testing Class.Call() from Util.ps1"
    $Test.Call()
}

Function Test-SubUtilTest {
    [CmdletBinding()]
    Param()

    Test-SubUtil
}

SubUtil.ps1

Write-Host "Calling from SubUtil.ps1"
$MyInvocation | Show-Object

Function Test-SubUtil {
    [CmdletBinding()]
    Param()

    Write-Host "Calling from Test-Util in Util.ps1"
    $MyInvocation | Show-Object 

    <# 
        here $MyInvocation.ScriptName, PSCommandPath show Util.ps1 NOT 
        main.ps1 as it is called from Util.ps1 
    #>
}

Main.ps1

. C:\Users\jenny\Class.ps1
. C:\Users\jenny\Util.ps1
. C:\Users\jenny\SubUtil.ps1

Write-Host "From Main.ps1"
$MyInvocation | Show-Object

write-host "Calling Test-Util from util.ps1"
Test-Util

Write-Host "Calling Test-Class from util.ps1"
Test-Class

write-host "Calling Test-SubUtil from Util.ps1"
Test-SubUtilTest

$Test = [Test]::new()

and

$Test.Call()

are both executed from util.ps1

yet the $MyInvocation only shows me main.ps1

How do I from either the Constructor of the class or one of its methods determine the ps1 file its calling code originates from when its in this kind of a nested dot source setup

I have tried swapping to & instead of . and I've also tried just moving the dot source of the class.ps1 to the util.ps1 file but it still tells me main.ps1 is the source.

Plus the real class file is a singleton meant to be used across multiple dot sourced util.ps1 files and I'm not sure if I can dot source the same class file in multiple files that are each dot sourced into main.ps1 (not that moving the dot source into the single utility file in this example made a difference)

Finally I'm using Show-Object from the PowerShellCookbook module.

It seems odd that it works for a function based nested call but not for a call to a class

Questioner
TofuBug
Viewed
82
mhu 2019-07-03 22:43

You could use the stack to determine the caller:

class Test {
    Test() {
        Get-PSCallStack | Select-Object -First 1 -Skip 1 -ExpandProperty "Location" | Write-Host
    }

    [void] Call() {
        Get-PSCallStack | Select-Object -First 1 -Skip 1 -ExpandProperty "Location" | Write-Host
    }
}