PowerShell is extremely flexible and provides cmdlet developers (and PowerShell users) a lot of opportunities to adjust the behavior of the system. One of the ways is formatting display output.
Have you ever wondered how PowerShell decides which columns to display when you run Get-Process? It actually uses *Format.ps1xml files to look up the columns to display. The information in the files includes column titles, width, and the actual data to be used. Even more, you are not limited to using just the properties which the actual objects have – your column headers can be different from the property names or can even be calculated dynamically using scriptblocks.
This is extremely powerful and allows you to change the formatting for yourself without having to ask cmdlet developers to change the code. However, if you are a cmdlet developer please never use this flexibility because you might really confuse your users.
Here’s a quick example of how this confusion can happen (start your PowerShell prompt and try it yourself):
Let’s start by checking out the newest 10 Application log events:
PS C:\> get-eventlog -logname Application -newest 10
Index Time Type Source EventID Message
----- ---- ---- ------ ------- -------
1349 May 11 18:31 Info Windows Error Rep... 1001 Fault bucket 346834087, type 1...
1348 May 11 18:31 Erro Application Error 1000 Faulting application agentsvr.exe, version 5.2.3790.1241, tim...
1347 May 11 18:29 Info Windows Error Rep... 1001 Fault bucket 347717822, type 1...
1346 May 11 18:29 Erro Application Error 1000 Faulting application agentsvr.exe, version 5.2.3790.1241, tim...
1345 May 11 18:28 Info Windows Error Rep... 1001 Fault bucket 347717822, type 1...
1344 May 11 18:28 Erro Application Error 1000 Faulting application agentsvr.exe, version 5.2.3790.1241, tim...
1343 May 11 17:55 Info SceCli 1704 Security policy in the Group policy objects has been applied ...
1342 May 11 14:12 Info Outlook 32 The store C:UsersdsotnikoMail2006.pst has detected a cata...
1341 May 11 14:11 Info Outlook 32 The store C:UsersdsotnikoMailTheArchive.pst has detected ...
1340 May 11 14:11 Info Outlook 32 The store C:UsersdsotnikoMailIDM.pst has detected a catal...
We get a nice well-formatted table. Everything is good. Well, until we start trying to use the columns of the table. For example, let’s try changing the set of columns so we only see EventID, Type, and Time:
PS C:\> get-eventlog -logname Application -newest 10 | Format-Table EventID, Type, Time
EventID Type Time
------- ---- ----
1001
1000
1001
1000
1001
1000
1704
32
32
32
What happened? Why Type and Time columns are empty now? This is because such properties actually do not exist and are a result of formatting made in the xml files.
We cannot sort by Type either:
PS C:\> get-eventlog -logname Application -newest 10 | Sort-Object Type
Index Time Type Source EventID Message
----- ---- ---- ------ ------- -------
1343 May 11 17:55 Info SceCli 1704 Security policy in the Group policy objects has been applied ...
1344 May 11 18:28 Erro Application Error 1000 Faulting application agentsvr.exe, version 5.2.3790.1241, tim...
1342 May 11 14:12 Info Outlook 32 The store C:UsersdsotnikoMail2006.pst has detected a cata...
1340 May 11 14:11 Info Outlook 32 The store C:UsersdsotnikoMailIDM.pst has detected a catal...
1341 May 11 14:11 Info Outlook 32 The store C:UsersdsotnikoMailTheArchive.pst has detected ...
1348 May 11 18:31 Erro Application Error 1000 Faulting application agentsvr.exe, version 5.2.3790.1241, tim...
1349 May 11 18:31 Info Windows Error Rep... 1001 Fault bucket 346834087, type 1...
1347 May 11 18:29 Info Windows Error Rep... 1001 Fault bucket 347717822, type 1...
1345 May 11 18:28 Info Windows Error Rep... 1001 Fault bucket 347717822, type 1...
1346 May 11 18:29 Erro Application Error 1000 Faulting application agentsvr.exe, version 5.2.3790.1241, tim...
Nor can we filter by Type:
PS C:\> get-eventlog -logname Application -newest 10 | where {$_.Type -eq Error}
You must provide a value expression on the right-hand side of the '-eq' operator.
At line:1 char:66
+ get-eventlog -logname Application -newest 10 | where {$_.Type -eq
PS C:\> get-eventlog -logname Application -newest 10 | where {$_.Type -eq Erro}
You must provide a value expression on the right-hand side of the '-eq' operator.
At line:1 char:66
+ get-eventlog -logname Application -newest 10 | where {$_.Type -eq
Of course the workaround is to use native properties instead and replace in the examples above Type with EntryType, and Time with TimeGenerated. The same workarounds work for PowerGUI (which is indeed affected and shows “pseudo-properties” just fine but fails to sort and filter by them). But if you are a cmdlet developer I beg you to not make your users search for those workarounds and keep your formatting simple: no scriptblocks and no titles mismatching property names.
And if you don’t believe me check-out Jeffrey’s blog post on how formatting really works.
Tags: cmdlets, PowerShell, software development
Like this:
Like Loading...