Directly constructed .NET type instances lack properties that ones output by cmdlets have
See original GitHub issueUpdate: See also this later proposal to provide the provider properties via class-backed CodeProperty members rather than per-instance NoteProperty members.
From what I can tell, this discrepancy has always existed, so there may be a good reason for it, but it deserves an explanation / documentation.
Specifically, where do the extra properties come from? They appear not to be part of the ETS type data as returned by Get-TypeData System.IO.DirectoryInfo
(and there’s also none for the parent type, Get-TypeData System.IO.FileSystemInfo
).
The absence of the .PSPath
property from the directly constructed [System.IO.DirectoryInfo]
and [System.IO.FileInfo]
instances is especially problematic, because pipeline-binding to -LiteralPath
parameters is based on it.
The types used are just an example; the same discrepancy exists for other types, such as [datetime]::now
vs. Get-Date
.
Steps to reproduce
# Construct seemingly identical [System.IO.DirectoryInfo] instances
([System.IO.DirectoryInfo] '/').psextended | Format-List
'---'
(Get-Item '/').psextended | Format-List
Expected behavior
PSPath : Microsoft.PowerShell.Core\FileSystem::/
PSParentPath :
PSChildName :
PSDrive : /
PSProvider : Microsoft.PowerShell.Core\FileSystem
PSIsContainer : True
Mode : d-r---
BaseName : /
Target :
LinkType :
---
PSPath : Microsoft.PowerShell.Core\FileSystem::/
PSParentPath :
PSChildName :
PSDrive : /
PSProvider : Microsoft.PowerShell.Core\FileSystem
PSIsContainer : True
Mode : d-r---
BaseName : /
Target :
LinkType :
Actual behavior
Mode : d-r---
BaseName : /
Target :
LinkType :
---
PSPath : Microsoft.PowerShell.Core\FileSystem::/
PSParentPath :
PSChildName :
PSDrive : /
PSProvider : Microsoft.PowerShell.Core\FileSystem
PSIsContainer : True
Mode : d-r---
BaseName : /
Target :
LinkType :
As you can see, the PS
-prefixed properties only exist on the instance output by Get-Item
.
Environment data
PowerShell Core v6.0.0-beta.4 on macOS 10.12.5
PowerShell Core v6.0.0-beta.4 on Ubuntu 16.04.2 LTS
PowerShell Core v6.0.0-beta.4 on Microsoft Windows 10 Pro (64-bit; v10.0.15063)
Windows PowerShell v5.1.15063.413 on Microsoft Windows 10 Pro (64-bit; v10.0.15063)
Issue Analytics
- State:
- Created 6 years ago
- Reactions:2
- Comments:24 (14 by maintainers)
@SteveL-MSFT describes a current pattern, but it doesn’t make it a good pattern.
To use the
Get-Process
example, I thinkGet-Process -IncludeUserName
is a bit gross.UserName
seems important enough that it should always be available on aProcess
object, and ETS was designed for just that scenario.If I want the user name in the output, then I’d rather see
Get-Process | Format-Table -View ProcessWithUserName
or something like that.To expand a bit on how we abuse ETS unnecessarily in the name of formatting, I’ll point out an idea first introduced by @KirkMunro in FormatPx.
The basic idea is that formatting directives are attached to an object without relying on the typename. This has the benefit of binding your formats in a script, e.g.:
And use the function like this:
So in this example, my function
Get-Process
fully specifies the default formatting while writing instances ofSystem.Diagnostics.Process
that can be used normally and later have a different format applied.FormatPx works like this using the existing format system, and I’ve implemented this idea in PSMore which is just barely functional as a prototype.
In summary, I’d like to see PowerShell move away from adding members to each instance and use type members as much as possible. I think this would be a win from a performance and usability point of view.
I would love to see the Format cmdlets work like that – still return usable objects, just with the formatting directives altered – wow!
That would save a significant amount of confusion for newbies, give us a way to simply and easily specify default formats programatically, the whole deal. Love it!