【问题标题】:How to access variable from calling PowerShell module scope from a called function contained in another module?如何从另一个模块中包含的被调用函数调用 PowerShell 模块范围访问变量?
【发布时间】:2018-02-25 03:50:30
【问题描述】:

运行以下将创建两个模块,其中一个调用一个函数,另一个调用函数尝试引用包含调用函数的模块范围内的变量:

$ModulePath = $env:PSModulePath.Split(";")[0]

New-Item -ItemType Directory -Path $ModulePath\TestModule1 -Force

@"
`$var = 1
function Write-Stuff {
    `$var
}
function Test-WriteStuff {
    Write-Stuff
    Write-Stuff2
}
"@ | Out-File $ModulePath\TestModule1\TestModule1.psm1

New-Item -ItemType Directory -Path $ModulePath\TestModule2 -Force

@"
function Write-Stuff2 {
    `$var
    "`r`nGet-Variable -Scope 0`r`n"
    Get-Variable -Scope 0

    "`r`nGet-Variable -Scope 1`r`n"
    Get-Variable -Scope 1

    "`r`nGet-Variable -Scope 2`r`n"
    Get-Variable -Scope 2

    "`r`nGet-Variable -Scope 3`r`n"
    Get-Variable -Scope 3
}
"@ | Out-File $ModulePath\TestModule2\TestModule2.psm1

这导致以下输出显示$Var 在被调用函数可访问的任何范围内都不是可用变量:

PS C:\Users\user> Test-WriteStuff
1

Get-Variable -Scope 0


Name                           Value                                                                                                                                                                                           
----                           -----                                                                                                                                                                                           
args                           {}                                                                                                                                                                                              
false                          False                                                                                                                                                                                           
input                          System.Collections.ArrayList+ArrayListEnumeratorSimple                                                                                                                                          
MaximumAliasCount              4096                                                                                                                                                                                            
MaximumDriveCount              4096                                                                                                                                                                                            
MaximumErrorCount              256                                                                                                                                                                                             
MaximumFunctionCount           4096                                                                                                                                                                                            
MaximumVariableCount           4096                                                                                                                                                                                            
MyInvocation                   System.Management.Automation.InvocationInfo                                                                                                                                                     
null                                                                                                                                                                                                                           
PSBoundParameters              {}                                                                                                                                                                                              
PSCommandPath                  C:\Users\cmagnuson\OneDrive - tervis.com\Documents\WindowsPowerShell\Modules\testmodule2\testmodule2.psm1                                                                                       
PSScriptRoot                   C:\Users\cmagnuson\OneDrive - tervis.com\Documents\WindowsPowerShell\Modules\testmodule2                                                                                                        
true                           True                                                                                                                                                                                            

Get-Variable -Scope 1

args                           {}                                                                                                                                                                                              
Error                          {}                                                                                                                                                                                              
false                          False                                                                                                                                                                                           
MaximumAliasCount              4096                                                                                                                                                                                            
MaximumDriveCount              4096                                                                                                                                                                                            
MaximumErrorCount              256                                                                                                                                                                                             
MaximumFunctionCount           4096                                                                                                                                                                                            
MaximumVariableCount           4096                                                                                                                                                                                            
MyInvocation                   System.Management.Automation.InvocationInfo                                                                                                                                                     
null                                                                                                                                                                                                                           
PSCommandPath                  C:\Users\cmagnuson\OneDrive - tervis.com\Documents\WindowsPowerShell\Modules\testmodule2\testmodule2.psm1                                                                                       
PSDefaultParameterValues       {}                                                                                                                                                                                              
PSScriptRoot                   C:\Users\cmagnuson\OneDrive - tervis.com\Documents\WindowsPowerShell\Modules\testmodule2                                                                                                        
true                           True                                                                                                                                                                                            

Get-Variable -Scope 2

$                              testmodule2                                                                                                                                                                                     
?                              True                                                                                                                                                                                            
^                              ipmo                                                                                                                                                                                            
args                           {}                                                                                                                                                                                              
ConfirmPreference              High                                                                                                                                                                                            
ConsoleFileName                                                                                                                                                                                                                
DebugPreference                SilentlyContinue                                                                                                                                                                                
Error                          {The scope number '3' exceeds the number of active scopes....                                                                                                                                   
ErrorActionPreference          Continue                                                                                                                                                                                        
ErrorView                      NormalView                                                                                                                                                                                      
ExecutionContext               System.Management.Automation.EngineIntrinsics                                                                                                                                                   
false                          False                                                                                                                                                                                           
FormatEnumerationLimit         4                                                                                                                                                                                               
HOME                           C:\Users\cmagnuson                                                                                                                                                                              
Host                           System.Management.Automation.Internal.Host.InternalHost                                                                                                                                         
InformationPreference          SilentlyContinue                                                                                                                                                                                
input                          System.Collections.ArrayList+ArrayListEnumeratorSimple                                                                                                                                          
MaximumAliasCount              4096                                                                                                                                                                                            
MaximumDriveCount              4096                                                                                                                                                                                            
MaximumErrorCount              256                                                                                                                                                                                             
MaximumFunctionCount           4096                                                                                                                                                                                            
MaximumHistoryCount            4096                                                                                                                                                                                            
MaximumVariableCount           4096                                                                                                                                                                                            
ModulePath                     C:\Users\cmagnuson\OneDrive - tervis.com\Documents\WindowsPowerShell\Modules                                                                                                                    
MyInvocation                   System.Management.Automation.InvocationInfo                                                                                                                                                     
NestedPromptLevel              0                                                                                                                                                                                               
null                                                                                                                                                                                                                           
OutputEncoding                 System.Text.SBCSCodePageEncoding                                                                                                                                                                
PID                            9552                                                                                                                                                                                            
profile                        C:\Users\cmagnuson\OneDrive - tervis.com\Documents\WindowsPowerShell\Microsoft.PowerShellISE_profile.ps1                                                                                        
ProgressPreference             Continue                                                                                                                                                                                        
PSBoundParameters              {}                                                                                                                                                                                              
PSCommandPath                                                                                                                                                                                                                  
PSCulture                      en-US                                                                                                                                                                                           
PSDefaultParameterValues       {}                                                                                                                                                                                              
PSEdition                      Desktop                                                                                                                                                                                         
PSEmailServer                                                                                                                                                                                                                  
PSHOME                         C:\Windows\System32\WindowsPowerShell\v1.0                                                                                                                                                      
psISE                          Microsoft.PowerShell.Host.ISE.ObjectModelRoot                                                                                                                                                   
PSScriptRoot                                                                                                                                                                                                                   
PSSessionApplicationName       wsman                                                                                                                                                                                           
PSSessionConfigurationName     http://schemas.microsoft.com/powershell/Microsoft.PowerShell                                                                                                                                    
PSSessionOption                System.Management.Automation.Remoting.PSSessionOption                                                                                                                                           
PSUICulture                    en-US                                                                                                                                                                                           
psUnsupportedConsoleApplica... {wmic, wmic.exe, cmd, cmd.exe...}                                                                                                                                                               
PSVersionTable                 {PSVersion, PSEdition, PSCompatibleVersions, BuildVersion...}                                                                                                                                   
PWD                            C:\Users\cmagnuson                                                                                                                                                                              
ShellId                        Microsoft.PowerShell                                                                                                                                                                            
StackTrace                        at System.Management.Automation.SessionStateInternal.GetScopeByID(Int32 scopeID)...                                                                                                          
true                           True                                                                                                                                                                                            
VerbosePreference              SilentlyContinue                                                                                                                                                                                
WarningPreference              Continue                                                                                                                                                                                        
WhatIfPreference               False                                                                                                                                                                                           

Get-Variable -Scope 3

Get-Variable : The scope number '3' exceeds the number of active scopes.
Parameter name: scopeID
Actual value was 3.
At C:\Users\cmagnuson\OneDrive - tervis.com\Documents\WindowsPowerShell\Modules\testmodule2\testmodule2.psm1:21 char:5
+     Get-Variable -Scope 3
+     ~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [Get-Variable], PSArgumentOutOfRangeException
    + FullyQualifiedErrorId : ArgumentOutOfRange,Microsoft.PowerShell.Commands.GetVariableCommand

尝试这样做的原因是使 PSTemplateEngine 能够正常工作,而无需有人传入带有变量名称和值或类似 -ArguementsList 的哈希表,然后要求他们在模板中有一个参数块.

Invoke-ProcessTemplatePath 特别可以指向一个树结构,其中包含许多文件,每个文件都包含许多变量。一个虚构的-ArguementsList 可能包含 40 个值,并且每个模板文件都必须有一个参数块 40 个参数,因为参数是按位置传递的。哈希表会更好,但如果可能的话,我仍然想避免它。

如何在不传递哈希表、$Var 的值、$(Get-Variable) 值的参数等的情况下从调用函数的模块范围内访问变量 $Var

【问题讨论】:

    标签: powershell


    【解决方案1】:

    模块存在于它们自己的世界中;它不是一个范围,但它有点像一个范围。 From about_Scopes:

    会话、模块和嵌套提示是自包含的环境, 但它们不是会话中全局范围的子范围。

    模块的隐私行为类似于作用域,但将模块添加到 session 不会改变范围。而且,该模块没有它的 自己的范围,虽然模块中的脚本,像所有 Windows PowerShell 脚本,确实有自己的作用域。

    因此,您将无法使用范围语义从另一个模块访问一个模块中的变量。

    You can export a variable from one of the modules using Export-ModuleMember -Variable.

    我不完全了解该模板引擎是什么或做什么,但从表面上看,您尝试做的事情听起来非常错误。

    将值作为参数传递可能是将数据传递给函数的正确方法。

    【讨论】:

    • PSTemplateEngine 允许您获取文本,例如 Zookeeper.properties 文件,并通过执行 "$TervisKafkaModulePath\zookeeper.properties.pstemplate" | Invoke-ProcessTemplateFile | Out-File -Encoding ascii -NoNewline "$($KafkaHome.FullName)\config\zookeeper.properties" 之类的操作来评估所有 PowerShell 变量和子表达式
    【解决方案2】:

    由于 OP 没有提到他们实际上是如何解决问题的(仅提及哈希表,但没有描述它是如何完成的),因此我将用一种方法来充实它,因为它可能并不明显。

    首先我创建一个变量来测试,因为您的环境将包含其他变量,我想演示访问其中一个变量。下一行加载一个哈希表,其中包含对当前作用域可访问的所有变量的引用。然后可以将哈希表传递给任何函数。

    $x = 'Some value'
    $a = Get-ChildItem variable:|&{begin{$h=@{}}process{$h[$_.name]=$_}end{$h}}
    

    因为哈希表存储了引用,所以变量的内容是可以修改的。

    $a['x'].value = 'A different value'
    

    因此,OP 代码的工作副本可能如下所示:

    $ModulePath = $env:PSModulePath.Split(";")[0]
    
    @'
    $var = 1
    function Write-Stuff {
        $var
    }
    function Test-WriteStuff {
        Write-Stuff
        $a = Get-ChildItem variable:|&{begin{$h=@{}}process{$h[$_.name]=$_}end{$h}}
        Write-Stuff2 $a
        Write-Stuff
    }
    '@ | Out-File $ModulePath\TestModule1\TestModule1.psm1
    
    @'
    function Write-Stuff2 {
        param ($all)
        $all['var'].value
        $all['var'].value=101
    }
    '@ | Out-File $ModulePath\TestModule2\TestModule2.psm1
    

    结果会在哪里

    1
    1
    101
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-04-17
      • 2015-11-17
      • 1970-01-01
      • 2016-05-15
      • 2015-09-19
      • 2020-12-30
      • 1970-01-01
      相关资源
      最近更新 更多