有没有办法让 powershell 模块进入其调用者的范围? [英] Is there any way for a powershell module to get at its caller's scope?

查看:40
本文介绍了有没有办法让 powershell 模块进入其调用者的范围?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一组实用函数和其他代码,我将它们点源到我编写的每个 powershell 文件中.受到调用方作用域变量的影响后,我开始考虑将其更改为 powershell 模块.

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 started looking into changing it into a powershell module.

我在做一些特殊的事情时遇到了问题,实际上我确实希望在范围之间进行一些交互.我想知道是否有任何方式进入"模块调用者的范围以在转移到 powershell 模块时保留此功能?

I ran into problems with a couple of the special things I do in it where I actually do want some interaction between the scopes. I'm wondering if there is anyway to "get at" the scope of a module's caller to keep this functionality while moving to a powershell module?

如果不是,我将这些更专业的东西保存在一个点源文件中并将更传统的实用程序功能移动到一个模块中是我最好的方法吗?以下是不容易移动到模块中的内容:

If not, is my best path forward to keep these more specialized things in a dot-sourced file and move the more traditional utility functions into a module? Here are the things that don't easily move to a module:

  • 设置严格模式和错误操作首选项以保持理智,例如:

  • Setting strict mode and error action preferences to keep sane, e.g.:

Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
$PSDefaultParameterValues['*:ErrorAction']='Stop'

当代码从 .psm1 powershell 模块运行时,这(正如预期的那样)对调用者的环境没有影响.有什么办法可以从 psm1 范围跨越到调用方范围来进行这些更改吗?

This (as expected) has no effect on the caller's environment when the code is run from a .psm1 powershell module. Is there any way to cross from the psm1 scope to the caller scope to make these changes?

打印出有关顶级脚本调用的信息,例如:

Printing out information about the top-level script call, e.g.:

$immediateCallerPath = Get-Variable -scope 1 -name PSCommandPath -ValueOnly
Write-Host "Starting script at $immediateCallerPath"
$boundParameters = Get-Variable -scope 1 -name PSBoundParameters -ValueOnly
Write-Host "Bound parameters are:"
foreach($psbp in $boundParameters.GetEnumerator())
{
        "({0},{1})" -f $psbp.Key,$psbp.Value | Write-Host
}

同样,这些命令一旦放在 .psm1 文件中就无法再看到最顶层的调用范围

Likewise, these commands can no longer see the top-most calling scope once placed in a .psm1 file

推荐答案

$PSCmdlet.SessionState 似乎在脚本模块内部提供了一个函数来访问调用站点的变量,前提是调用站点位于模块.(如果调用点在模块内部,你可以只使用 Get-Set-Variable -Scope.)这是一个使用 SessionState 的例子>:

$PSCmdlet.SessionState seems to provide a function inside a script module access to the call site's variables provided the call site is outside the module. (If the call site is inside the module, you can just use Get- and Set-Variable -Scope.) Here is an example using SessionState:

New-Module {
    function Get-CallerVariable {
        param([Parameter(Position=1)][string]$Name)
        $PSCmdlet.SessionState.PSVariable.GetValue($Name)
    }
    function Set-CallerVariable {
        param(
            [Parameter(ValueFromPipeline)][string]$Value,
            [Parameter(Position=1)]$Name
        )
        process { $PSCmdlet.SessionState.PSVariable.Set($Name,$Value)}
    }
} | Import-Module

$l = 'original value'
Get-CallerVariable l
'new value' | Set-CallerVariable l
$l

哪个输出

original value
new value

我不确定 SessionState 是否打算以这种方式使用.就其价值而言,这与 Get-CallerPreference 中使用的技术相同.ps1.还有一些测试用例这里是PowerShell pass版本 2 到 5.1.

I'm not sure whether SessionState was intended to be used in this manner. For what it's worth, this is the same technique used in Get-CallerPreference.ps1. There are also some test cases here which pass on PowerShell versions 2 through 5.1.

这篇关于有没有办法让 powershell 模块进入其调用者的范围?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆