如何从另一个模块中包含的被调用函数调用PowerShell模块作用域来访问变量?

时间:2017-04-24 19:05:39

标签: powershell

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

$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,而不传递散列表,$Var的值,一个参数值$(Get-Variable)等?

2 个答案:

答案 0 :(得分:3)

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

  

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

     

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

所以你不能使用范围语义从另一个模块访问一个模块中的变量。

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

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

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

答案 1 :(得分:0)

由于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