Powershell: Different types of objects in a variable couldnot be displayed in correct format except for the 1st type of object

Created on 22 Sep 2018  路  19Comments  路  Source: PowerShell/PowerShell

_From @shidouli on September 21, 2018 7:36_

Steps to reproduce

PS C:\windows\system32> $vars = @($vm, $vmhost)
PS C:\windows\system32> $vars

Name                 PowerState Num CPUs MemoryGB
----                 ---------- -------- --------
test                 PoweredOff 1        0.250
WARNING: The 'State' property of VMHost type is deprecated. Use the 'ConnectionState' property instead.
WARNING: PowerCLI scripts should not use the 'DatastoreIdList' property of VMHost type. The property will be removed in a future release.

State                 : Connected
ConnectionState       : Connected
PowerState            : PoweredOn
VMSwapfileDatastoreId :
VMSwapfilePolicy      : Inherit
ParentId              : ClusterComputeResource-domain-c7
IsStandalone          : False
Manufacturer          : VMware, Inc.
Model                 : VMware Virtual Platform
NumCpu                : 2
CpuTotalMhz           : 4794
CpuUsageMhz           : 44
LicenseKey            : 
MemoryTotalMB         :
MemoryTotalGB         : 
MemoryUsageMB         : 
MemoryUsageGB         : 
ProcessorType         : Intel(R) Xeon(R) CPU E5-2680 v4 @ 2.40GHz
HyperthreadingActive  : False
TimeZone              : UTC
Version               : 6.8.1
Build                 : 
Parent                : cl
VMSwapfileDatastore   :
StorageInfo           : HostStorageSystem-storageSystem-12
NetworkInfo           : 
DiagnosticPartition   : mpx.vmhba0:C0:T1:L0
FirewallDefaultPolicy : VMHostFirewallDefaultPolicy:HostSystem-host-12
ApiVersion            : 6.7.1
MaxEVCMode            : intel-broadwell
Name                  : 
CustomFields          : {[AutoDeploy.MachineIdentity, ]}
ExtensionData         : VMware.Vim.HostSystem
Id                    : 
Uid                   :
DatastoreIdList       : {Datastore-datastore-13, Datastore-datastore-14, Datastore-datastore-15, Datastore-datastore-16...}

PS C:\windows\system32> $vars = @($vmhost, $vm)
PS C:\windows\system32> $vars

Name                 ConnectionState PowerState NumCpu CpuUsageMhz CpuTotalMhz   MemoryUsageGB   MemoryTotalGB Version
----                 --------------- ---------- ------ ----------- -----------   -------------   ------------- -------
10.10.10.10       Connected       PoweredOn       2          44        4794           1.202           7.999   6.8.1
WARNING: The 'Version' property of VirtualMachine type is deprecated. Use the 'HardwareVersion' property instead.

Name                    : test
PowerState              : PoweredOff
Notes                   :
Guest                   : test:
NumCpu                  : 1
CoresPerSocket          : 1
MemoryMB                : 256
MemoryGB                : 0.25
VMHostId                : HostSystem-host-12
VMHost                  : 
VApp                    :
FolderId                : Folder-group-v3
Folder                  : vm
ResourcePoolId          : ResourcePool-resgroup-8
ResourcePool            : Resources
HARestartPriority       : ClusterRestartPriority
HAIsolationResponse     : AsSpecifiedByCluster
DrsAutomationLevel      : AsSpecifiedByCluster
VMSwapfilePolicy        : Inherit
VMResourceConfiguration : CpuShares:Normal/1000 MemShares:Normal/2560
Version                 : v14
HardwareVersion         : vmx-14
PersistentId            : 502014c2-3fd8-50c5-1a2e-493f429dd1f7
GuestId                 : winXPProGuest
UsedSpaceGB             : 0.0390625
ProvisionedSpaceGB      : 1.4974369313567876815795898438
DatastoreIdList         : {Datastore-datastore-14}
ExtensionData           : VMware.Vim.VirtualMachine
CustomFields            : {}
Id                      : VirtualMachine-vm-23
Uid                     : 

Expected behavior

Both the $vm and $vmhost should be displayed in its own correct format, not be shown with the full properties

Actual behavior

The object after the 1st type object would be shown with full properties, not with its own defined format.

Environment data

dotnet --info output:

PS C:\windows\system32> dotnet --info
.NET Command Line Tools (2.1.103)

Product Information:
 Version:            2.1.103
 Commit SHA-1 hash:  60218cecb5

Runtime Environment:
 OS Name:     Windows
 OS Version:  10.0.15063
 OS Platform: Windows
 RID:         win10-x64
 Base Path:   C:\Program Files\dotnet\sdk\2.1.103\

Microsoft .NET Core Shared Framework Host

  Version  : 2.0.6
  Build    : 74b1c703813c8910df5b96f304b0f2b78cdf194d

Issue-Question Resolution-Duplicate

Most helpful comment

This is essentially a duplicate of #4552 (which was closed as Resolution-by-Design), created by @JohnLBevan.

Here's @SteveL-MSFT's conclusion from that issue:

I agree that this trips up people and open to suggestions on how to enhance this, however, it should probably be a RFC

To summarize the current behavior (note that I'm describing inferred behavior - I haven't checked the source code):

The output formatting system is designed for objects of the _same type_.

With disparate types, the 1st output object locks in the implicitly applied Format-* cmdlet, and, if _Format-Table_ is selected (whether as directed by a format definition of whether implicitly based on <= 4 properties present), the specific _columns_ are locked in too, and subsequent objects of different type may not render at all, or only partially, depending on whether they happen to have property names that overlap with the first object's.
If the 1st output object has a _custom_ view, then it seems that subsequent objects of different type are rendered with something like ... | Format-List *, so in that sense their format definitions aren't being honored, as @vexx32 states.

However, I don't think the behavior is related to the 300ms wait, because the behavior predates the wait, which was only introduced in v5. However, the wait produces its own problems - see #4594.

All 19 comments

Moved this to the powershell repo as this seems like a PS issue and not a .NET Core one.

Hi @shidouli, thanks for opening an issue.

In addition to the details above, can you also provide the output in PowerShell of:

$PSVersionTable

Name Value
---- -----
PSVersion 5.1.15063.1155
PSEdition Desktop
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...}
BuildVersion 10.0.15063.1155
CLRVersion 4.0.30319.42000
WSManStackVersion 3.0
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1

Thanks for the extra information @shidouli.

Issues in Windows PowerShell are handled in UserVoice.

However, re-reading the issue, this looks like a problem in the PowerCLI module rather than Windows PowerShell -- if you're expecting a certain format, that should be provided by them in a .format.ps1xml file.

The best option is probably to contact the owners of the PowerCLI module -- the gallery should have a solution for that here under the "Contact Owners" link.

Hi Robert,

No, we have the format.ps1.xml file for each type. For each type, it could be displayed with its own type correctly.

But if multiple types are in an array variable, then this array variable could show the correct format for the 1st type elements in its array.

I'm not an expert in this area, but after reading through the issues, https://github.com/PowerShell/PowerShell/issues/4552 seems relevant.

Yes, relevant, but not the same. This issue is more easy to reproduce, just simple put 2 different types in an array variable, output the variable, and then change the 2 elements' order, output the array variable, you'll see the difference.

Anyway, thanks for the info, I'll file a bug in UserVoice.

@SteveL-MSFT, @mklement0 While this is presenting in Windows PowerShell, I haven鈥檛 checked to see if the behaviour is any different in PowerShell Core.

I suspect this is by design and based on how PowerCLI have written their format.ps1xml, but need someone with more expertise on formatting to evaluate.

I checked it in MacOs with PowerShell Core 6.1, same issue happened.

This strikes me as possibly related to the issue where outputting multiple PSCustomObjects with different sets of properties 'hides' later ones.

It's less severe than that, thanks to the objects being of a different type, but it does seem like it's only processing the first object's format file. I would water that the code that waits, what is, 300 ms or so, and attempts to group output, is glitching this and isn't checking the format file of the second object.

This is because they are 2 different objectin an array

@shidouli do you get the same issue if you where to do the following

$vars = @($vmhost, $vm)
$vars | Foreach-Object { $PSItem | Out-Default}

^^ this worked for me using Hyper-V VM's and Disk Objects with the following code
``` powershell
$vars = @((Get-VM), (Get-Disk))
$vars | Foreach-Object { $PSItem | Out-Default}

This is essentially a duplicate of #4552 (which was closed as Resolution-by-Design), created by @JohnLBevan.

Here's @SteveL-MSFT's conclusion from that issue:

I agree that this trips up people and open to suggestions on how to enhance this, however, it should probably be a RFC

To summarize the current behavior (note that I'm describing inferred behavior - I haven't checked the source code):

The output formatting system is designed for objects of the _same type_.

With disparate types, the 1st output object locks in the implicitly applied Format-* cmdlet, and, if _Format-Table_ is selected (whether as directed by a format definition of whether implicitly based on <= 4 properties present), the specific _columns_ are locked in too, and subsequent objects of different type may not render at all, or only partially, depending on whether they happen to have property names that overlap with the first object's.
If the 1st output object has a _custom_ view, then it seems that subsequent objects of different type are rendered with something like ... | Format-List *, so in that sense their format definitions aren't being honored, as @vexx32 states.

However, I don't think the behavior is related to the 300ms wait, because the behavior predates the wait, which was only introduced in v5. However, the wait produces its own problems - see #4594.

The current behavior is a limitation of the original design optimized (or constrained if you prefer) to display objects of the same type. Note that derived types will work, just disparate types won't be displayed. As noted by @mklement0 I'm open to a RFC to propose a solution on how to handle this. Consider if you have an array of a,a,b,a,b,a where [a] and [b] are different types. How would these be displayed? Should they be grouped by type and then displayed or interleave different tables which makes it hard to read. Of course grouping means that it would have to capture all the output before it can start rendering or cache all objects not the same as the first type which can use lots of memory.

Would outputting a Warning: Object of type [foo] was not displayed be a good thing or not?

How significant do you think the performance overhead of the interleaved tables / respecting each cmdlet's standard formatting would be?

Outputting the objects in a grouped fashion has a similar issue to the current behaviour: it misrepresents the actual underlying data structures being passed along here, causing users to erroneously think the data is neatly sorted, and misrepresenting the order of elements.

That would be, in my opinion, the best solution. You'd end up with some extra whitespace, I'm sure, but it accurately represents the overall structure of the underlying data properly, nothing is hidden, and the user can clearly see the state of things (and easily correct if need be)

Not entirely sold on the warning, but it would still be a marked improvement.

@vexx32 since we have experimental flags, someone could implement a solution where every new type just outputs a new table and we can see how that experience would be before we commit to a more permanent change

Aight, I'm game. Would I need to do anything special to make it work with an experimental flag? Not familiar with that stuff yet.

Was this page helpful?
0 / 5 - 0 ratings