Powershell 正在重新激活脚本中的变量
Powershell is reanimating variables in Scripts
晚上好
这个版本有问题
PS C:\temp> $PSVersionTable.PSVersion.Major
4
这真是一个奇怪的问题...
尽管有初始化的变量,PowerShell 脚本还是能够以某种方式重用以前调用的变量值。
脚本简单;为了显示问题,我使用了一个虚拟机列表:
- 将所有虚拟机读入一个数组
- Select 数组中的第一个元素
- 向第 2 步中的对象添加一个新的 属性
- 问题:如果我第二次 运行 脚本,新的 属性 已经存在 - 尽管所有变量都已初始化。如果我在新会话中启动脚本,新的 属性 在第一个 运行 丢失,之后它已经在那里了。
这是简单的代码:
Set-StrictMode -Version 2.0
# Read all Virtual Machines into an Array
$AllVMs = @()
$AllVMs = Get-VM
# Get the 1st Virtual Machine
$VM = $null
$VM = $AllVMs[0]
# Prepare my Property
$MyList = @()
$MyList += "Test"
# If the Property already exists, just add my List
if ($VM.PSobject.Properties.Name -match "MyList") {
$VM.MyList += $MyList
} else {
# My Property does not exist: create it
$VM | Add-Member –MemberType NoteProperty –Name MyList –Value ($MyList)
}
# Give Back my VM Object
$VM
为了测试脚本,我只计算了 MyList-Elements 的数量:
PS C:\temp> $result = c:\temp\testvar.ps1
PS C:\temp> $result.MyList.Count
1
PS C:\temp> $result = c:\temp\testvar.ps1
PS C:\temp> $result.MyList.Count
2
…
有人可以帮我解决这个问题吗?
非常感谢您的帮助!!
亲切的问候,
汤姆
我也向 'the scripting guy' Forum 问过这个问题。
我有两个很好的答案:
来自 jrv:
您没有退出 PowerShell。 VM 对象对于会话是动态的。它会一直存在,直到您关闭 PowerShell。有些对象是这样的。代码库将它们拖到 PowerShell 中并保持缓存状态。我怀疑这就是这里发生的事情。
来自 Evgenij Smirnov:
嗨,
这似乎特定于 VM 对象。如果我用 Get-Process 或 Get-ChildItem c:\ 替换 Get-VM,我不会遇到这种行为。如果我每次 运行 脚本时 select 一个新的 VM,它不会保留 属性。另一方面,如果我在 运行 执行脚本四次后执行 (Get-VM)[0].MyList,我会得到四个条目。
所以这种持久性显然内置于 Hyper-V 模块中,自定义 属性 被添加到 VM 对象本身的实例中。因此,您可以像这样在整个 VM 集合上将 MyTest 初始化为空:
$AllVMs | foreach {
if ($_.PSobject.Properties.Name -match "MyList") {
$_.MyList = @()
}
}
此致,汤姆
晚上好
这个版本有问题
PS C:\temp> $PSVersionTable.PSVersion.Major
4
这真是一个奇怪的问题... 尽管有初始化的变量,PowerShell 脚本还是能够以某种方式重用以前调用的变量值。
脚本简单;为了显示问题,我使用了一个虚拟机列表:
- 将所有虚拟机读入一个数组
- Select 数组中的第一个元素
- 向第 2 步中的对象添加一个新的 属性
- 问题:如果我第二次 运行 脚本,新的 属性 已经存在 - 尽管所有变量都已初始化。如果我在新会话中启动脚本,新的 属性 在第一个 运行 丢失,之后它已经在那里了。
这是简单的代码:
Set-StrictMode -Version 2.0
# Read all Virtual Machines into an Array
$AllVMs = @()
$AllVMs = Get-VM
# Get the 1st Virtual Machine
$VM = $null
$VM = $AllVMs[0]
# Prepare my Property
$MyList = @()
$MyList += "Test"
# If the Property already exists, just add my List
if ($VM.PSobject.Properties.Name -match "MyList") {
$VM.MyList += $MyList
} else {
# My Property does not exist: create it
$VM | Add-Member –MemberType NoteProperty –Name MyList –Value ($MyList)
}
# Give Back my VM Object
$VM
为了测试脚本,我只计算了 MyList-Elements 的数量:
PS C:\temp> $result = c:\temp\testvar.ps1
PS C:\temp> $result.MyList.Count
1
PS C:\temp> $result = c:\temp\testvar.ps1
PS C:\temp> $result.MyList.Count
2
…
有人可以帮我解决这个问题吗?
非常感谢您的帮助!!
亲切的问候, 汤姆
我也向 'the scripting guy' Forum 问过这个问题。
我有两个很好的答案:
来自 jrv:
您没有退出 PowerShell。 VM 对象对于会话是动态的。它会一直存在,直到您关闭 PowerShell。有些对象是这样的。代码库将它们拖到 PowerShell 中并保持缓存状态。我怀疑这就是这里发生的事情。来自 Evgenij Smirnov:
嗨,
这似乎特定于 VM 对象。如果我用 Get-Process 或 Get-ChildItem c:\ 替换 Get-VM,我不会遇到这种行为。如果我每次 运行 脚本时 select 一个新的 VM,它不会保留 属性。另一方面,如果我在 运行 执行脚本四次后执行 (Get-VM)[0].MyList,我会得到四个条目。
所以这种持久性显然内置于 Hyper-V 模块中,自定义 属性 被添加到 VM 对象本身的实例中。因此,您可以像这样在整个 VM 集合上将 MyTest 初始化为空:
$AllVMs | foreach {
if ($_.PSobject.Properties.Name -match "MyList") {
$_.MyList = @()
}
}
此致,汤姆