You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Get-FormatData doesn't report formatting data for some types for which formatting data ships with PowerShell. #4237
PowerShell Core v6.0.0-beta.3 on macOS 10.12.5
PowerShell Core v6.0.0-beta.3 on Ubuntu 16.04.1 LTS
PowerShell Core v6.0.0-beta.3 on Microsoft Windows 10 Pro (64-bit; v10.0.14393)
Windows PowerShell v5.1.15063.413 on Microsoft Windows 10 Pro (64-bit; v10.0.15063)
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 FileSystemTypes and 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.
I 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.
Thanks 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.1 to Get-FormatData calls in order to get output?
Since something like Get-FormatData System.Management.Automation.AliasInfo currently works as-is, to what types - other than the 2 mentioned (System.IO.DirectoryInfo, System.IO.FileInfo) - does this requirement to specify -PowerShellVersion apply?
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-FormatData couldn't have been used correctly, so those types are not returned.
Briefly, I think GroupBy, SelectCondition, and CustomControl are the items that trigger not getting returned by Get-FormatData unless you specify -PowerShellVersion 5.1.
The user should not have to specify anything and by default it should show all the formatters perhaps with a PowerShellVersion column. I believe -PowerShellVersion exists for remoting.
If it's possible to detect how Get-FormatData is 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.
You can test if the automatic $PSSenderInfo variable is present, which is only defined in remoting sessions. (For additional robustness, you can test whether its type is System.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 -PowerShellVersion just so you can see the current session's formatting data reliably.
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.
// $PSSenderInfo is defined in true remoting contexts and background jobs.// Its Boolean .PSShowComputerName NoteProperty is false only in background jobs.boolremoting=(GetVariableValue("PSSenderInfo")asPSObject)?.Properties["PSShowComputerName"]?.Valueisboolvalue&&value;boolwriteOldWay=remoting&&(PowerShellVersion==null||PowerShellVersion.Major<5||(PowerShellVersion.Major==5&&PowerShellVersion.Minor<1));
This is probably the best way to detect whether a cmdlet is running within a remote session in general.
But if this is a built-in cmdlet that has access to internal types the following will also work:
bool remoting = (this.Context.InternalHost.ExternalHost is ServerRemoteHost);
Background 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 ServerRemoteHost host.
Note the PowerShellVersion == null part of the original conditional, which means that the "old way" kicks in in the absence of a -PowerShellVersion argument as well.
That is, currently you always get the "old way" if you don't explicitly specify -PowerShellVersion 5.1 or higher - this awkward requirement is what prompted creation of this issue.
Therefore, we must ensure that background jobs aren't mistaken for remoting.
Paul Higinbotham (@PaulHigin), I think you may be missing that PowerShellVersion refers to a parameter, not to the executing PowerShell engine's version.
Activity
lzybkr commentedon Jul 13, 2017
This is a bug, but the repro should be:
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.
lzybkr commentedon Jul 13, 2017
I 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.
mklement0 commentedon Jul 25, 2017
Jason Shirk (@lzybkr)
Thanks 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?
lzybkr commentedon Jul 25, 2017
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.SteveL-MSFT commentedon Nov 28, 2017
The 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.lzybkr commentedon Nov 28, 2017
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.
SteveL-MSFT commentedon Oct 20, 2018
Paul Higinbotham (@PaulHigin) are you aware of there is a way for a cmdlet to detect it is being remotely?
mklement0 commentedon Sep 23, 2019
Steve Lee (@SteveL-MSFT):
You 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
lzybkr commentedon Nov 22, 2019
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.
SteveL-MSFT commentedon Nov 22, 2019
Paul Higinbotham (@PaulHigin), would what Michael Klement (@mklement0) proposes here work to detect remote usage?
mklement0 commentedon Nov 22, 2019
Sorry, 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:
PowerShell/src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/common/GetFormatDataCommand.cs
Lines 100 to 102 in 2f67253
with this:
PaulHigin commentedon Nov 25, 2019
This is probably the best way to detect whether a cmdlet is running within a remote session in general.
But if this is a
built-incmdlet that has access to internal types the following will also work:mklement0 commentedon Nov 25, 2019
Paul Higinbotham (@PaulHigin), but won't that return true for local-machine background jobs as well, which I presume we do not want?
PaulHigin commentedon Nov 25, 2019
You still have the version check. Background jobs will always run the current version of PowerShell.
mklement0 commentedon Nov 25, 2019
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 commentedon Nov 25, 2019
I 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 commentedon Nov 25, 2019
Note 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 commentedon Nov 25, 2019
Paul Higinbotham (@PaulHigin), I think you may be missing that
PowerShellVersionrefers to a parameter, not to the executing PowerShell engine's version.PaulHigin commentedon Nov 26, 2019
Yes, you are right. I think your code is the correct way.
Fix PowerShell#4237