我有一个从注册表中的卸载项派生的哈希表的通用列表,我需要对其进行搜索。每个列表成员都是包含这些键的有序字典。每个键的实际值是单独定义的,因为有些是直接来自注册表的值,有些是计算出来的。
[Ordered]@{
displayName = 'DisplayName'
displayVersion = 'DisplayVersion'
installSource = 'InstallSource'
publisher = 'Publisher'
quietUninstallString = 'QuietUninstallString'
uninstallParam = 'UninstallParam'
uninstallPath = 'UninstallPath'
uninstallString = 'UninstallString'
installDate = 'InstallDate'
keyID = '$keyID'
keyName = '$keyName'
keyGUID = '$keyGUID'
keyPath = '$keyPath'
architecture = '$architecture'
}
一旦我将此集合放入变量中
$rawUninstallKeys
,我需要搜索它,并且搜索很复杂,因为 Autodesk 往往有多个具有相同或相似数据的卸载密钥,但只有一个可以工作。例如,将有一个 DisplayName
为 Autodesk Revit 2025
的 GUID 密钥提供实际有效的卸载字符串,而另一个 DisplayName
为 Revit 2025
的 GUID 不执行任何操作。因此,要提取正确的 uninstallString,我需要搜索与第一个模式匹配的键,并且具有与第二个模式匹配的第二个键。实际上有很多变化,因为 Autodesk 在任何一致性方面都很糟糕。
所以,我现在正在工作,我只是在原始键上执行 foreach 来查找第一个模式,如果找到它,我会派生出第二个模式(在这种情况下,我将“Autodesk”替换为 $null
),然后搜索与另一个foreach。它确实有效,但亲爱的上帝,它很慢。
所以,我想尝试使用列表中的.Where()
方法来获得.NET优化。但这意味着构建一个要应用的闭包集合。
所以,这会起作用
$rawUninstallKeys.Where({$_.publisher -like "Autodesk*"})
但我正在努力解决如何将闭包放入变量中,但仍允许
$_
适当扩展。当我只需要查看该值是否存在时,我的闭包可能只是 {$_.DisplayName}
,或者当我只想要一个不包含该属性或第一个属性的键时,这使情况变得更加复杂。例如,我需要将属性值与另一个值(可能是通配符)进行比较。
实际上,我需要做的是扩展 {-not $_.DisplayName}
内闭包字符串中的变量,但这不起作用.Where()
.Where({$($ExecutionContext.InvokeCommand.ExpandString($closure))})
:
让我们设置一些测试数据:.Where()
然后,如果您想要应用一系列过滤器:
$rawUninstallKeys = [System.Collections.Generic.List[System.Collections.IDictionary]]::new()
$rawUninstallKeys.Add(
[ordered] @{
publisher = "Autodesk Revit 2025"
}
)
$rawUninstallKeys.Add(
[ordered] @{
displayname = "displayname"
publisher = "Revit 2025"
}
)
然后你可以这样做:
$filters = @(
{ $_.Publisher -like 'Autodesk*' },
{ $_.DisplayName }
)
给出输出:
foreach( $filters in $filter )
{
write-host "testing for $scriptblock"
$rawUninstallKeys.Where($closure) | ft | out-string
}
您可以扩展它以按顺序运行过滤器,直到找到第一个返回结果的过滤器,如果这是您需要的......