Is there any way for a powershell module to get at its caller's scope?

前端 未结 2 1451
鱼传尺愫
鱼传尺愫 2021-01-12 15:14

I have a collection of utility functions and other code that I dot-source into every powershell file I write. Having gotten bit by caller scope variables influencing it, I s

2条回答
  •  陌清茗
    陌清茗 (楼主)
    2021-01-12 15:48

    Not sure if I understand completely what you are after. I believe you would like to know where is the code implemented that invokes the cmdlets of you module. Maybe even further up.

    If I'm correct then you can use Get-PSCallStack to retrieve the stack trace. For example from an unsaved script it looks like this

    PS C:\Users\asarafian> Get-PSCallStack
    
    Command       Arguments Location 
    -------       --------- -------- 
     {}        
    

    If the file was saved then it would look like this

    PS C:\Users\asarafian> Get-PSCallStack
    
    Command       Arguments Location 
    -------       --------- -------- 
    File1.ps1           
    

    Depending on what you want to achieve, which is not clear to me, you need to walk the list from [0] which is the code that executed Get-PSCallStack to [x].

    When building the XWrite I wanted also to figure out if an entry from the stack was a script file, a cmdlet part of a module or unknown like .

    My implementation is in Get-XCommandSource.ps1 and it follows the following logic for the command value from the stacktrace

    1. if it ends with .ps1 then it's a script file.
    2. if it is then it's a script block.
    3. if the command can be loaded with Get-Command then
      1. if it has a module then it's a cmdlet in a module.
      2. if not then it's a cmdlet/function imported with .\cmdlet.ps1 pattern.

    Here is the implementation:

    function Get-XCommandSource
    {
        [CmdletBinding(SupportsShouldProcess=$true)]
        Param(
            [Parameter(Mandatory=$true)]
            [AllowEmptyString()]
            [AllowNull()]
            [string]$Command
        )
        begin {
    
        }
    
        process {
            if(-not $Command)
            {
                "Unknown"
            }
            elseif($Command.EndsWith(".ps1"))
            {
                "Script"
            }
            elseif($Command -eq "")
            {
                "Unknown"
            }
            else
            {
                $cmdlet=Get-Command -Name $command -ErrorAction SilentlyContinue
                if($cmdlet)
                {
                    $moduleName=$cmdlet|Select-Object -ExpandProperty ModuleName
    
                    if($moduleName)
                    {
                        $moduleName
                    }
                    else
                    {
                        "Function"
                    }
                }
                else
                {
                    "Unknown"
                }
            }
        }
    
        end {
    
        }
    }
    

提交回复
热议问题