运行以下命令将创建两个模块,其中一个模块在另一个模块中调用函数,其中被调用的函数尝试引用包含调用函数的模块范围内的变量:
$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能够正常工作,而不需要有人传入一个包含变量名称和值的哈希表或类似-ArgumentsList
的内容,然后要求他们在模板中有一个参数块。Invoke-ProcessTemplatePath
特别可能指向具有多个文件的树结构,每个文件都包含多个变量。单个虚构的-ArgumentsList
可能包含40个值,并且每个模板文件必须具有长达40个参数的参数块,因为这些参数是按位置传递的。哈希表会工作得更好,但如果可能的话,我还是想避免它。
如何从被调用函数访问调用函数模块作用域中的变量$Var
,而不传递哈希表、$Var
的值、值为$(Get-Variable)
的参数等?
2条答案
按热度按时间7vux5j2d1#
模块存在于它们自己的世界中;它不是一个作用域,但它的行为有点像作用域。From about_Scopes:
会话、模块和嵌套提示是自包含的环境,但它们不是会话中全局作用域的子范围。
模块的隐私行为类似于作用域,但将模块添加到会话不会更改作用域。此外,该模块没有自己的作用域,尽管该模块中的脚本与所有Windows PowerShell脚本一样都有自己的作用域。
因此,您将无法使用作用域语义从一个模块中访问另一个模块中的变量。
You can export a variable from one of the modules using
Export-ModuleMember -Variable
。我不完全理解模板引擎是什么或做什么,但从表面上看,您试图做的事情听起来非常错误。
将值作为参数传递可能是将数据传递给函数的正确方式。
djmepvbi2#
由于OP没有提到他们实际上是如何解决这个问题的(只提到了一个哈希表,但没有描述它是如何完成的),所以我将充实它的一种方法,因为它可能并不明显。
首先,我创建了一个用于测试的变量,因为您的环境将包含其他变量,我想演示如何访问其中一个变量。下一行加载一个哈希表,其中引用了可从当前作用域访问的所有变量。然后可以将哈希表传递给任何函数。
因为哈希表存储引用,所以可以修改变量的内容。
因此,OP代码的工作副本可能如下所示:
结果会是什么?