The Wiert Corner – irregular stream of stuff

Jeroen W. Pluimers on .NET, C#, Delphi, databases, and personal interests

  • My badges

  • Twitter Updates

  • My Flickr Stream

  • Pages

  • All categories

  • Enter your email address to subscribe to this blog and receive notifications of new posts by email.

    Join 2,977 other subscribers

Archive for November 12th, 2020

powershell – Format-Table forgets some properties, but Format-List shows them all. Why? – Stack Overflow

Posted by jpluimers on 2020/11/12

Reminder to self: finish the script that initiated this 2013 question (yes ages ago!) [WayBack] powershell – Format-Table forgets some properties, but Format-List shows them all. Why? – Stack Overflow.

The question was based on code I was really happy I saved in the WayBack machine: WayBack: how-to: Print/List installed programs/applications sorted by date | Tech Off | Forums | Channel 9

So here the question and the answer.


Given the below PowerShell 3 script, Format-Table does not list all properties as columns (it skips NoRemove), but Format-List does, and you can force the properties to be there using Select-Object.

Out-GridView behaves the same as Format-Table and also skips NoRemove

Why is that?

Note: this is from a much less restricted Where-Object clause, where it looks like Format-Tabledoes inspect more than just the first object in the array to guess the columns.

The example comes from Channel 9 how-to: Print/List installed ​programs/ap​plications sorted by date which forgot to initialize the first Get-ItemProperty (gp) as an array so you got an error like this:

Method invocation failed because [Microsoft.Win32.RegistryKey] doesn't
contain a method named 'op_Addition'.

Example code:

$nonUninstallableSoftwareRegistryKeys = (@(Get-Item HKCU:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*)) + 
(Get-Item HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*) + 
(Get-Item HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*) | 
  Where-Object { $_.ValueCount -eq 1 }

$nonUninstallableSoftwareRegistryKeys | Get-Member

$nonUninstallableSoftwareRegistryNameValues = $nonUninstallableSoftwareRegistryKeys | 

$nonUninstallableSoftwareRegistryNameValues | Get-Member

$nonUninstallableSoftwareRegistryNameValues |

$nonUninstallableSoftwareRegistryNameValues |

$nonUninstallableSoftwareRegistryNameValues |
  Select-Object SystemComponent, NoRemove, PSPath, PSParentPath, PSChildName, PSProvider |

I used GetType().FullName and Get-Member to inspect the underlying types.

$nonUninstallableSoftwareRegistryKeys starts with all installed software (user, system x64 and system x86) filtered by registry keys having only 1 value (empirically those are the ones you cannot uninstall).

The first part of the output shows that $nonUninstallableSoftwareRegistryKeys is a System.Object[] of type Microsoft.Win32.RegistryKey with all the right members. Hence the ability to perform a Where-Object filter on the ValueCount property even though the code-completion does not show that.

$nonUninstallableSoftwareRegistryKeys exposes also a few PowerShell “Extended Type System” NoteProperty properties including Property that contain the registry Name/Value pairs under the key and a bunch of PS* coming from the registry provider.

$nonUninstallableSoftwareRegistryNameValues is also a System.Object[] but now of typeSystem.Management.Automation.PSCustomObject because of the Get-ItemProperty which expands the Name/Value pairs in the Property of each $nonUninstallableSoftwareRegistryKeysitem into properties. For the first item in my output, it adds the SystemComponent property. For the second item it adds NoRemove. And it adds a bunch of PS* coming from the registry provider.

Format-Table output:

SystemComponent PSPath                                                                                                                                    PSParentPath                        
--------------- ------                                                                                                                                    ------------                        
              1 Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall\Connection Manager             Microsoft.PowerShell.Core\Registr...
                Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall\WIC                            Microsoft.PowerShell.Core\Registr...
              1 Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Connection Manager Microsoft.PowerShell.Core\Registr...
                Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\WIC                Microsoft.PowerShell.Core\Registr...

Format-List output:

SystemComponent : 1
PSPath          : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall\Connection Manager
PSParentPath    : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall
PSChildName     : Connection Manager
PSProvider      : Microsoft.PowerShell.Core\Registry

NoRemove     : 1
PSPath       : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall\WIC
PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall
PSChildName  : WIC
PSProvider   : Microsoft.PowerShell.Core\Registry

SystemComponent : 1
PSPath          : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Connection Manager
PSParentPath    : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall
PSChildName     : Connection Manager
PSProvider      : Microsoft.PowerShell.Core\Registry

NoRemove     : 1
PSPath       : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\WIC
PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall
PSChildName  : WIC
PSProvider   : Microsoft.PowerShell.Core\Registry

Select-Object output:

SystemComponent NoRemove PSPath                                                                                                                                    PSParentPath               
--------------- -------- ------                                                                                                                                    ------------               
              1          Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall\Connection Manager             Microsoft.PowerShell.Cor...
                1        Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall\WIC                            Microsoft.PowerShell.Cor...
              1          Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Connection Manager Microsoft.PowerShell.Cor...
                1        Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\WIC                Microsoft.PowerShell.Cor...

Edit: my environment

PS C:\Users\Developer> Get-CimInstance Win32_OperatingSystem | Select-Object Version, Caption | Format-List

Version : 6.2.9200
Caption : Microsoft Windows 8 Pro

Name                           Value                                                                                                                                                          
----                           -----                                                                                                                                                          
PSVersion                      3.0                                                                                                                                                            
WSManStackVersion              3.0                                                                                                                                                            
CLRVersion                     4.0.30319.18051                                                                                                                                                
BuildVersion                   6.2.9200.16628                                                                                                                                                 
PSCompatibleVersions           {1.0, 2.0, 3.0}                                                                                                                                                
PSRemotingProtocolVersion      2.2   

These 2 return the same table:

$nonUninstallableSoftwareRegistryNameValues |

$nonUninstallableSoftwareRegistryNameValues |
  Format-Table *                                                                                                                                                         

Answer 1

If you don’t specify the property names or ‘*’ for all of them, Format-Table will print by default just the first 4 (the default value of $FormatEnumerationLimit), not ure why you get only three in the ft output. Format-List will show all only when the type of objects doesn’t have a format view for Format-List.


I did a $nonUninstallableSoftwareRegistryNameValues | Format-Table * which also skips NoRemove. Something fishy is going on here.

And if you add -Force?

This also fails: $nonUninstallableSoftwareRegistryNameValues | Format-Table * -Force

I can see all properties when piping to fl (without -force) and with ft *.

What OS and PS version do you run? I’ve added mine to my question.

Answer 2

Did you try the following?

$nonUninstallableSoftwareRegistryNameValues |
  Select-Object SystemComponent, NoRemove, PSPath, PSParentPath, PSChildName, PSProvider |
  Format-Table -Wrap


That works (it is almost the same as the last entry in my example), but why can’t Format-Table figure this out by itself? Or maybe phrased differently: what criteria does Format-Table to determine which columns to pick?


Posted in .NET, CommandLine, Development, PowerShell, PowerShell, Scripting, Software Development | Leave a Comment »

Me starting to understand the real life meanings of Shim

Posted by jpluimers on 2020/11/12

The combination of being partially word blind and having learned English initially from my urge to understand computing books during my (Dutch) secondary education in the mid 1980s, I often have a gap between understanding “daily life” or “real life” English words, especially when they also have a meaning in the computing world.

So it took me a while to get the non-computing meaning of shim.

In computing, shim is used as word for tiny shell that separates two layers, which means my original association was with “sphere”.

Had I associated with an adapter or something that puts space between to layers, it would have been much easier to understand the “real life” meaning of a spacer shim.

Similarly, I had trouble understanding washer (which I associated with washing, and is right: it often means washing machine, but can also mean dish washer, which is an odd word for me as it washes much more than dishes). It took me much longer to get there is an additional meaning for a mechanical construction washer, which is a thin disc (so not a tube-like ring) often used as spacers, so in a sense similar to a shim.

In Dutch, I have the same problem with “wasmachine” (English washing machine) and “afwasmachine” (Dish washer).

To add to the confusion, hardware washers in Dutch are called rings.


All of the above links are from Wikipedia.

Posted in About, LifeHacker, Personal, Power User | Leave a Comment »

Tracking down Delphi “abstract error” occassions.

Posted by jpluimers on 2020/11/12

A few tips.

  1. Set breakpoints in these units:
    • System.pas:
      procedure _AbstractError;
        if Assigned(AbstractErrorProc) then
        RunErrorAt(210, ReturnAddress);
    • System.SysUtils.pas:
      procedure AbstractErrorHandler;
        raise EAbstractError.CreateRes(@SAbstractError);
  2. add a watch for ClassName that has “Allow side effects and function calls” enabled
  3. run your code until it breaks or stops (usually in the first method above)
  4. double click on each entry in the “Call Stack” pane, and for each entry:
    • set a break point on the call to the method above it in the stack trace
    • note that sometimes this is on the line you arrived, but sometimes one more more lines higher in your code
    • the cause is that the stack trace will show you where your code will RETURN to, not the place it was CALLED FROM.
  5. abort your program
  6. run your program again
  7. on each hit breakpoint, watch the value of ClassName:
    • if it becomes [WayBackE2003: Undeclared identifier: 'ClassName', then:
      • observe the method directives
      • if it includes static, but it is actually inside a class, then remove the static

Sometimes you cannot perform the last step: class property definitions have to be backed by static class methods.

This usually means you have a bad design anyway: you depend on global/singleton kind of behaviour that is almost impossible to properly test.

A better approach is to have regular object instances for that, then use constructor dependency injection (maybe combined with factory or dependency injection container) to setup the structures of dependencies.


Create a conference summary on the use of class versus instance methods, and static/regular.

Base materials:


Posted in Conference Topics, Conferences, Delphi, Development, Event, Software Development | Leave a Comment »

%d bloggers like this: