运行以下命令将创建两个模块,其中一个调用另一个函数,其中被调用函数试图引用包含调用函数的模块范围内的变量:
$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)
等?
答案 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