How do I merge two "lists" in PowerShell when one list might be just one item from Get-Item?

26k views Asked by At

I am using Get-ChildItem to fetch locally installed certs. Then I'd like to delete these certs from my local certificate store. If I execute the script below it will work when there is more than one item returned in both the Get-ChildItem queries. But if only one item is returned in either of the queries the addition of the two collections will fail. Simply because with only one object returned the implementation only returns one instance and not a collection of one. What is the right approach here? I won't know if the result(s) returned from my queries will result in 0, 1 or multiple certs.

$myCerts = Get-ChildItem cert:\CurrentUser\My | Where-Object { $_.Subject -like "CN=$certName" }
$trustedPeopleCerts = Get-ChildItem cert:\CurrentUser\TrustedPeople | Where-Object { $_.Subject -like "CN=$certName" }

$allCerts = $myCerts + $trustedPeopleCerts

foreach ($cert in $allCerts) {
    $store = Get-Item $cert.PSParentPath
    $store.Open('ReadWrite')
    $store.Remove($cert)
    $store.Close()
}
3

There are 3 answers

0
Mathias R. Jessen On BEST ANSWER

If $myCerts might just be a single item, use the array subexpression operator @( ):

$allCerts = @($myCerts) + $trustedPeopleCerts
2
Matt On

Another solution that accomplishes the same thing is to use a unary comma operator to ensure that $myCerts is always an array. Consider the following examples that we are using for one element and 0 elements.

$myCerts = Get-Item C:\temp
$myCerts.GetType().FullName

$myCerts = $null
$myCerts.GetType().FullName

The above would generate System.IO.DirectoryInfo and an error for "call[ing] a method on a null-valued expression"

Now lets try the same thing with unary comma operator.

$myCerts = ,(Get-Item C:\temp)
$myCerts = ,($null)

The answer in both cases is System.Object[]

I forgot about one thing this is doing. @() might be preferential in this case as it is an array sub expression. The comma operator I think here is creating a multidimentional array. When used in a pipe it is unrolled and you still get the data you are looking for but it is an important difference to note.

1
mattmess1221 On

I found a way to do it using a pipeline in case arrays aren't playing nicely. This will write each item to the local pipeline inside the ScriptBlock, which gets captured to the variable.

$merged = & {
    $foo
    $bar
}