I have a Generic List of hash tables derived from Uninstall keys in the registry, which I need to search. Each list member is an ordered dictionary containing these keys. The actual value of each key is defined separately since some are values direct from the registry and some are calculated.
[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'
}
Once I have this collection in a variable $rawUninstallKeys
I need to search it, and the search is convoluted because Autodesk tends to have multiple uninstall keys with the same or similar data, but only one will work. For example there will be a GUID key with a DisplayName
of Autodesk Revit 2025
that provides a uninstall string that actually works and another GUID with a DisplayName
of Revit 2025
that does nothing. So to extract the correct uninstallString I need to search for a key that matches the first pattern AND has a second key that matches the second pattern. And there are actually a ton of variations because Autodesk just sucks at any kind of consistency.
So, I have this working now where I just do a foreach on the raw keys looking for the first pattern, and if I find it I derive the second pattern (in this case I replace ‘Autodesk ‘ with $null
) and then search with another foreach. And it does work, but dear god it’s slow.
So, I want to try using the .Where()
method on the list to get the .NET optimization. But that means building a collection of closures to apply.
So, this will work
$rawUninstallKeys.Where({$_.publisher -like "Autodesk*"})
but I am struggling with how to get the closure into a variable that still allows $_
to expand appropriately. This is further complicated by the fact that my closure might simply be {$_.DisplayName}
when I just need to see if that value exists at all, or {-not $_.DisplayName}
when I only want a key that doesn’t contain that property, or the first example where I need to compare the properties value to another value, which may be a wildcard.
Effectively what I kind of need to do is expand the variable in the closure string within the .Where()
, but this doesn’t work
.Where({$($ExecutionContext.InvokeCommand.ExpandString($closure))})