我有以下脚本:
$serverList = @{
"Server1Name" = @{ "WindowsService1" = "Status"; "WindowsService2" = "Status" };
"Server2Name" = @{ "WindowsService1" = "Status"; "WindowsService2" = "Status" };
"Server3Name" = @{ "WindowsService1" = "Status" };
"Server4Name" = @{ "WindowsService1" = "Status" };
"Server5Name" = @{ "WindowsService1" = "Status" };
"Server6Name" = @{ "WindowsService1" = "Status" }
}
$copy = $serverList.Clone()
foreach ($server in $copy.Keys) {
foreach ($service in $copy[$server].Keys) {
$serviceInfo = Get-Service -ComputerName $server -Name $service
$serverList[$server][$service] = $serviceInfo.Status
}
}
我确保我没有修改被枚举的哈希表,但是当我运行脚本时仍然会出现此错误:
Collection was modified; enumeration operation may not execute.At line:14 char:14
+ foreach ($service in $copy[$server].Keys) {
+ ~~~~~~~~
+ CategoryInfo : OperationStopped: (:) [], InvalidOperationException
+ FullyQualifiedErrorId : System.InvalidOperationException
我在这里读到了这个:http://blog.matticus.net/2013/11/powershell-clearing-values-within.html。如果我在那里复制代码表单,它对我来说没有错误。
我的问题可能与嵌套的foreach循环有关吗?我的代码中有错误吗?任何人都可以对此有所了解吗?
答案 0 :(得分:3)
Powershell不喜欢你正在修改你正在迭代的集合。
一开始你创建了一个名为$ copy的克隆来避免这个问题。 clone()
是一个“浅拷贝”,因此每个密钥所指的对象在您的副本中是相同的。
在这一行:
$serverList[$server][$service] = $serviceInfo.Status
您修改内部集合 - 您当前正在迭代它。
实际上,外部集合永远不会被修改,只会被引用,因此外部clone()调用是不必要的。相反,您应该克隆内部集合。 像这样(未经测试):
$serverList = @{
"Server1Name" = @{ "WindowsService1" = "Status"; "WindowsService2" = "Status" };
"Server2Name" = @{ "WindowsService1" = "Status"; "WindowsService2" = "Status" };
"Server3Name" = @{ "WindowsService1" = "Status" };
"Server4Name" = @{ "WindowsService1" = "Status" };
"Server5Name" = @{ "WindowsService1" = "Status" };
"Server6Name" = @{ "WindowsService1" = "Status" }
}
foreach ($server in $serverList.Keys) {
$copy = $serverList[$server].clone();
foreach ($service in $copy.Keys) {
$serviceInfo = Get-Service -ComputerName $server -Name $service
$serverList[$server][$service] = $serviceInfo.Status
}
}
答案 1 :(得分:1)
我很惊讶.Clone()方法只是创建对同一对象的新引用,它不会创建具有相同属性的新对象。我找不到一种简单的方法来实际复制整个哈希表,而不是克隆它。所以我写了一个函数来做到这一点:
Function Copy-HashTable($HashTable) {
$newHash = @{}
$HashTable.GetEnumerator() | ForEach-Object {
if ($_.Value -is "Hashtable") {
$newHash[$_.Key] = Copy-HashTable $_.Value
} else {
$newHash[$_.Key] = $_.Value
}
}
$newHash
}
将此应用于您的代码,您只需要替换
行$copy = $serverList.Clone()
带
$copy = Copy-HashTable $ServerList