I was using PowerShell to do some batch operation to my contacts. Before applying the operations, I need to filter out the contacts of interest based on their names and email addresses. Given that intensively accessing Outlook objects is rather slow due to the marshaling nature, it is wise to first
select
the properties in which we’re interested, find out the objects of interest and finally go back to the real COM objects. When I usedSort-Object
to sort the contacts, the objects seem to have been mysteriously altered by theSort-Object
cmdlet. How could this happen?
Long story short, I had some contacts duplicated. The duplicates had the same FullName
, but without any other information, e.g., email addresses or homepage. I ran the following commands interactively:
# Outlook automation
$outlookApp = New-Object -ComObject Outlook.Application
$mapi = $outlookApp.GetNamespace('MAPI')
# Select the ‘Contacts’ folder of my Microsoft account
$contactsFolder = $mapi.PickFolder()
# Enumerate the objects
$contacts = $contactsFolder.Items | Write-Output
# Select these properties:
# FullName,
# Email1Address, Email1AddressType, Email1DisplayName, Email1EntryID,
# Email2Address, Email2AddressType, Email2DisplayName, Email2EntryID,
# Email3Address, Email3AddressType, Email3DisplayName, Email3EntryID
$contactsLight = $contacts | Select-Object FullName, Email*
# Have a look at them
# Looks good
$contactsLight | Out-GridView
If I want to finish my job, I could just invoke $contactsLight | Group-Object FullName | Where-Object Count -gt 1
and inspect the result to see if they are duplicates or just people with the same name. However, I tried this:
# The properties are gone!
# The columns are DisplayName and Email*
$contactsLight | Sort-Object FullName | Out-GridView
How could this happen? Is there a subtle bug in PSCustomObject
? Does PowerShell have a special deal (and bug) with Select-Object
and Sort-Object
?
I tried this:
$contactsLight | ConvertTo-Json | Set-Content 1.json
$contactsLight = Get-Content 1.json | ConvertFrom-Json
# Still altered!
$contactsLight | Sort-Object FullName | Out-GridView
# I suspect PowerShell sets some magic in the 1.json file.
# So I launder the thing by putting it to the clipboard.
Get-Content 1.json | Set-Clipboard
# Restart PowerShell and continue
$contactsLight = Get-Clipboard | ConvertFrom-Json
# How could PowerShell still get this wrong
# even after a fresh restart?!
$contactsLight | Sort-Object FullName | Out-GridView
I even tried copying the content to a Mac and use PowerShell for macOS. Still no luck! What the heck?! Here’s the reason.
I even tried copying the content to a Mac and use PowerShell for macOS. Still no luck! What the heck?! The reason is that the ‘Contacts’ folder contains not only contacts but also distribution lists, which don’t have FullName
or Email*
. The selected objects sorted, these objects gets to the top. PowerShell decides the properties to display by the member set of the first object, so 🤣… Here’s a conceptual reproduction:
$objects =
@{ 'FullName' = 'Example'; 'Email1' = 'someone@example.com'; 'Email2' = '' },
@{ 'Name' = 'Friends'; 'Members' = @('someone@example.com', 'sometwo@example.com') } |
ForEach-Object { [pscustomobject]$_ } |
Select-Object FullName, Email*
$objects | Format-List
# FullName : Example
# Email1 : someone@example.com
# Email2 :
#
# FullName :
# Email* :
$objects # | Format-Table
# Note the empty line!
# FullName Email1 Email2
# -------- ------ ------
# Example someone@example.com
#
$object | Sort-Object FullName | Format-List
# FullName :
# Email* :
#
# FullName : Example
# Email1 : someone@example.com
# Email2 :
$object | Sort-Object FullName # | Format-Table
# Note the empty line!
# FullName Email*
# -------- ------
#
# Example
So Sort-Object
didn’t alter the objects. It’s how they are formatted that has changed 🤣.
Don’t invent a global conspiracy too early.
Please enable JavaScript to view the comments powered by Disqus.