首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >有什么方法可以让powershell模块访问调用方的作用域吗?

有什么方法可以让powershell模块访问调用方的作用域吗?
EN

Stack Overflow用户
提问于 2017-10-02 15:04:52
回答 2查看 1.8K关注 0票数 7

我有一个实用程序函数和其他代码的集合,我把这些代码点到我编写的每个powershell文件中。在受到了影响它的调用范围变量的影响后,我开始研究将其更改为powershell模块。

我遇到了一些问题,我在其中做的一些特殊的事情,我确实想要在作用域之间进行一些交互。我想知道是否存在“获取”模块调用方的作用域,以便在迁移到powershell模块时保留此功能?

如果不是,我的最佳路径是将这些更专业的东西保存在点源文件中,并将更传统的实用程序函数转移到模块中吗?下面是一些不易移动到模块的东西:

  • 设置严格的模式和错误操作首选项以保持理智,例如: Set-StrictMode -Version最新$ErrorActionPreference =“停止”$ErrorActionPreference 当代码从.psm1 powershell模块运行时,这(如预期的)对调用方的环境没有任何影响。是否有任何方法可以从psm1作用域到调用方作用域进行这些更改?
  • 打印有关顶级脚本调用的信息,例如: $immediateCallerPath =Get-变量-scope 1 -name PSCommandPath -ValueOnly写-主机“起始脚本at $immediateCallerPath”$boundParameters =Get-变量-scope 1 -name PSBoundParameters -ValueOnly写-主机“绑定参数为:”foreach($psbp in $boundParameters.GetEnumerator()) { "({0},{1})“-f $psbp.Key,$psbp.Value \Write Host} 同样,这些命令一旦放置在.psm1文件中,就无法再看到最顶层的调用范围。
EN

回答 2

Stack Overflow用户

发布于 2017-10-12 21:11:36

$PSCmdlet.SessionState似乎在脚本模块中提供了一个函数,只要调用站点在模块之外,就可以访问调用站点的变量。(如果调用站点位于模块内,则只需使用Get-Set-Variable -Scope。)下面是一个使用SessionState的示例

代码语言:javascript
运行
复制
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

哪种输出

代码语言:javascript
运行
复制
original value
new value

我不确定SessionState是否打算以这种方式使用。无论它的价值如何,这都是Get-CallerPreference.ps1中使用的相同技术。还有一些测试用例这里,它们传递PowerShell版本2到5.1。

票数 6
EN

Stack Overflow用户

发布于 2017-10-03 08:20:34

不知道我是否完全明白你想要的是什么。我相信您想知道调用您模块的cmdlet的代码在哪里实现。甚至更高的位置。

如果我是正确的,那么您可以使用Get-PSCallStack检索堆栈跟踪。例如,从未保存的脚本中看,它如下所示

代码语言:javascript
运行
复制
PS C:\Users\asarafian> Get-PSCallStack

Command       Arguments Location 
-------       --------- -------- 
<ScriptBlock> {}        <No file>

如果保存了该文件,则如下所示

代码语言:javascript
运行
复制
PS C:\Users\asarafian> Get-PSCallStack

Command       Arguments Location 
-------       --------- -------- 
File1.ps1           <No file>

根据您想要实现的目标(我不太清楚),您需要从[0] (执行Get-PSCallStack[x]的代码)遍历列表。

在构建XWrite时,我还想知道堆栈中的条目是脚本文件、模块的cmdlet部分还是未知的<ScriptBlock>

我的实现是在Get-XCommandSource.ps1中实现的,它遵循以下逻辑,用于堆栈跟踪中的命令值

  1. 如果它以.ps1结尾,那么它就是一个脚本文件。
  2. 如果它是<ScriptBlock>,那么它就是一个脚本块。
  3. 如果可以用Get-Command加载命令,那么
    1. 如果它有一个模块,那么它就是模块中的cmdlet。
    2. 如果不是,则是用.\cmdlet.ps1模式导入的cmdlet/函数。

以下是实现:

代码语言:javascript
运行
复制
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 "<scriptblock>")
        {
            "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 {

    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46528262

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档