如何无需显式指定属性名访问PowerShell嵌套Hashtable属性?
问题分析与解决
一、你的错误点
- foreach遍历对象错误:直接遍历
$programs哈希表时,foreach ($Name in $programs)中的$Name实际是哈希表的值(即每个@{DisplayName=...; Program=...}的嵌套哈希表),但你代码里操作的是$programs.Keys——这是外层哈希表的键集合(program1、program2),和内层属性完全无关,自然取不到有效值导致null错误。 - 属性访问语法错误:即便拿到正确的嵌套哈希表,
$programs.Keys['DisplayName']这种写法也不成立,Keys是哈希表的键集合,不是属性容器,无法通过它直接访问内层属性。
二、正确的遍历写法
不需要显式指定外层键名(比如program1)的话,直接遍历哈希表的值即可,代码如下:
foreach ($program in $programs.Values) { # 从当前嵌套哈希表中获取属性值 $displayName = $program['DisplayName'] $programPath = $program['Program'] $r = Get-NetFirewallRule -DisplayName $displayName 2> $null if (-not $r) { New-NetFirewallRule -DisplayName $displayName -Program $programPath } }
如果需要同时获取外层键名和对应值,可以遍历哈希表的枚举器:
foreach ($entry in $programs.GetEnumerator()) { $outerKey = $entry.Key # 比如program1 $program = $entry.Value # 嵌套哈希表 $displayName = $program['DisplayName'] $programPath = $program['Program'] # 后续逻辑同上 }
三、无需指定层级列出所有DisplayName属性
1. 二级嵌套场景
直接遍历外层哈希表的值,提取每个值里的DisplayName:
# 写法一 $programs.Values | ForEach-Object { $_['DisplayName'] } # 写法二(更简洁) ($programs.Values).DisplayName
2. 多级嵌套(比如四级)场景
如果DisplayName固定在深层或可能出现在任意层级,可通过递归遍历自动查找所有目标键对应的值,无需写死层级路径:
function Find-NestedValue { param( [Parameter(Mandatory, ValueFromPipeline)] $InputObject, [string]$KeyName ) process { if ($InputObject -is [hashtable]) { # 检查当前哈希表是否包含目标键 if ($InputObject.ContainsKey($KeyName)) { $InputObject[$KeyName] } # 递归遍历当前哈希表的所有值 foreach ($value in $InputObject.Values) { Find-NestedValue -InputObject $value -KeyName $KeyName } } # 如果是数组/集合,遍历每个元素继续查找 elseif ($InputObject -is [System.Collections.IEnumerable] -and $InputObject -isnot [string]) { foreach ($item in $InputObject) { Find-NestedValue -InputObject $item -KeyName $KeyName } } } } # 调用示例:查找四级嵌套哈希表中的所有DisplayName Find-NestedValue -InputObject $multiLevelHashtable -KeyName 'DisplayName'
内容的提问来源于stack exchange,提问作者user20225877
相关产品推荐
相关产品推荐

