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.
Question
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 skipsNoRemove
Why is that?
Note: this is from a much less restricted
Where-Object
clause, where it looks likeFormat-Table
does 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/applications 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.GetType().FullName $nonUninstallableSoftwareRegistryKeys | Get-Member $nonUninstallableSoftwareRegistryNameValues = $nonUninstallableSoftwareRegistryKeys | Get-ItemProperty $nonUninstallableSoftwareRegistryNameValues.GetType().FullName $nonUninstallableSoftwareRegistryNameValues | Get-Member $nonUninstallableSoftwareRegistryNameValues | Format-Table $nonUninstallableSoftwareRegistryNameValues | Format-List $nonUninstallableSoftwareRegistryNameValues | Select-Object SystemComponent, NoRemove, PSPath, PSParentPath, PSChildName, PSProvider | Format-Table
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 aSystem.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 includingProperty
that contain the registry Name/Value pairs under the key and a bunch ofPS*
coming from the registry provider.
$nonUninstallableSoftwareRegistryNameValues
is also aSystem.Object[]
but now of typeSystem.Management.Automation.PSCustomObject because of the Get-ItemProperty which expands the Name/Value pairs in theProperty
of each$nonUninstallableSoftwareRegistryKeys
item 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 ofPS*
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 $PSVersionTable Version : 6.2.9200 Caption : Microsoft Windows 8 Pro Name Value ---- ----- PSVersion 3.0 WSManStackVersion 3.0 SerializationVersion 1.1.0.1 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 | Format-Table $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 forFormat-List
.Comment
I did a
$nonUninstallableSoftwareRegistryNameValues | Format-Table *
which also skipsNoRemove
. 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
Comment
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 doesFormat-Table
to determine which columns to pick?
–jeroen