Repository navigation
Get-FormatData doesn't report formatting data for some types for which formatting data ships with PowerShell. #4237
Description
Activity
This is a bug, but the repro should be:
Get-FormatData System.IO.DirectoryInfo, System.IO.FileInfo -PowerShellVersion 5.1
This extra parameter was added in 5.1 so remoting would work between older clients and newer servers. The format data returned before 5.1 was incomplete and in some ways wrong, e.g. the file system types were returned as
FileSystemTypesand it didn't actually work - the real type names were lost.That said, there is still a bug, I'm not quite sure where it is though.
Reacted by Michael KlementI should add - the format data for help is intentionally never returned - I forget the exact reason I did that - I think there were problems with serialization depth being exceeded and I decided it wasn't important to return those formats anyway.
- addedWG-Enginecore PowerShell engine, interpreter, and runtimecore PowerShell engine, interpreter, and runtimeIssue-BugIssue has been identified as a bug in the productIssue has been identified as a bug in the product
on Jul 13, 2017 mklement0 commented
on Jul 25, 2017 ContributorAuthorMore actionsThanks for clarifying, but just so I get the full picture:
Are you saying that even with the bug fixed it will be necessary to add
-PowerShellVersion 5.1toGet-FormatDatacalls in order to get output?Since something like
Get-FormatData System.Management.Automation.AliasInfocurrently works as-is, to what types - other than the 2 mentioned (System.IO.DirectoryInfo,System.IO.FileInfo) - does this requirement to specify-PowerShellVersionapply?Is there an explicit list or some abstract criterion?
In the abstract - some format data properties were missing before 5.1. If those properties were non-null, then the format data returned by
Get-FormatDatacouldn't have been used correctly, so those types are not returned.To be concrete, look at the implementations of PSControl.CompatibleWithOldPowerShell
Briefly, I think GroupBy, SelectCondition, and CustomControl are the items that trigger not getting returned by
Get-FormatDataunless you specify-PowerShellVersion 5.1.Reacted by Michael KlementThe user should not have to specify anything and by default it should show all the formatters perhaps with a
PowerShellVersioncolumn. I believe-PowerShellVersionexists for remoting.If it's possible to detect how
Get-FormatDatais called, then it would be possible to return all formatters with no arguments, but only when called locally. If called from a remote client, then it's important to determine the client version and not return objects that won't deserialize.I'm not aware of any cmdlet that does something like this today, so I'm not sure how easy it would be.
Paul Higinbotham (@PaulHigin) are you aware of there is a way for a cmdlet to detect it is being remotely?
mklement0 commented
on Sep 23, 2019 ContributorAuthorMore actionsYou can test if the automatic
$PSSenderInfovariable is present, which is only defined in remoting sessions. (For additional robustness, you can test whether its type isSystem.Management.Automation.Remoting.PSSenderInfo, given that PowerShell doesn't prevent you from manually assigning to this variable in local sessions).Please note that PR #8063 didn't fix this issue, only a closely related one, so can you please re-open this one?
The issue is still that you shouldn't have to use
-PowerShellVersionjust so you can see the current session's formatting data reliably.1 remaining item
Thomas Nieto (@ThomasNieto) - the default value for a remote session must be compatible with older clients that are unaware of the parameter and hence do not specify it. This include Windows PowerShell v5.0 and earlier.
For the local case, maybe a different default is possible.
Paul Higinbotham (@PaulHigin), would what Michael Klement (@mklement0) proposes here work to detect remote usage?
mklement0 commented
on Nov 22, 2019 ContributorAuthorMore actionsSorry, Steve Lee (@SteveL-MSFT): my previous attempt to distinguish true remoting from background jobs was flawed.
I hope the following works robustly.
Please note the assumption made in the comments, which should be confirmed.
From what I can tell, all that is needed is to replace this:
Lines 100 to 102 in 2f67253
bool writeOldWay = PowerShellVersion == null || PowerShellVersion.Major < 5 || (PowerShellVersion.Major == 5 && PowerShellVersion.Minor < 1); with this:
// $PSSenderInfo is defined in true remoting contexts and background jobs. // Its Boolean .PSShowComputerName NoteProperty is false only in background jobs. bool remoting = (GetVariableValue("PSSenderInfo") as PSObject)?.Properties["PSShowComputerName"]?.Value is bool value && value; bool writeOldWay = remoting && ( PowerShellVersion == null || PowerShellVersion.Major < 5 || (PowerShellVersion.Major == 5 && PowerShellVersion.Minor < 1) );
PaulHigin commented
on Nov 25, 2019 ContributorMore actionsThis is probably the best way to detect whether a cmdlet is running within a remote session in general.
But if this is abuilt-incmdlet that has access to internal types the following will also work:bool remoting = (this.Context.InternalHost.ExternalHost is ServerRemoteHost);mklement0 commented
on Nov 25, 2019 ContributorAuthorMore actionsPaul Higinbotham (@PaulHigin), but won't that return true for local-machine background jobs as well, which I presume we do not want?
PaulHigin commented
on Nov 25, 2019 ContributorMore actionsYou still have the version check. Background jobs will always run the current version of PowerShell.
mklement0 commented
on Nov 25, 2019 ContributorAuthorMore actionsBackground jobs will always run the current version of PowerShell.
Yes, which is why the version check shouldn't be done for background jobs, as in my code above.
If you only check for the host, you'll get a false positive for background jobs, given that true remoting and background jobs both use the
ServerRemoteHosthost.PaulHigin commented
on Nov 25, 2019 ContributorMore actionsI guess I'm confused. You will never have a background job with version < 5.1, so the write is always the new way. Isn't that what we want?
mklement0 commented
on Nov 25, 2019 ContributorAuthorMore actionsNote the
PowerShellVersion == nullpart of the original conditional, which means that the "old way" kicks in in the absence of a-PowerShellVersionargument as well.That is, currently you always get the "old way" if you don't explicitly specify
-PowerShellVersion 5.1or higher - this awkward requirement is what prompted creation of this issue.Therefore, we must ensure that background jobs aren't mistaken for remoting.
mklement0 commented
on Nov 25, 2019 ContributorAuthorMore actionsPaul Higinbotham (@PaulHigin), I think you may be missing that
PowerShellVersionrefers to a parameter, not to the executing PowerShell engine's version.PaulHigin commented
on Nov 26, 2019 ContributorMore actionsYes, you are right. I think your code is the correct way.
Reacted by Michael Klement- added a commit that references this issue
on Dec 5, 2019
I haven't looked into the logic behind which types' formatting data isn't being reported, but two examples are below.
A counter example is
Get-FormatData System.Management.Automation.AliasInfo, which works as expected.Steps to reproduce
Expected behavior
[System.Management.Automation.ExtendedTypeDefinition]instances describing the formatting, as usual.Actual behavior
No output is produced;
$?indicates$True.Yet, formatting data is clearly in effect.
In Windows PowerShell, it can be discovered as follows:
Environment data