Are You My Type?
Even though PowerShell is built on the .NET Framework, you have never been required to be a .NET developer to use PowerShell. Microsoft designed PowerShell for IT Pros to get work done quickly and easily. This is possible because PowerShell abstracts the complexity of .NET and provides a simplified interface for working with objects. Instead of having to know about the Kill()
method of the Process
class and how to invoke it, you can simply use the Stop-Process
cmdlet. Instead of being forced to know about the ServicesDependedOn
property of System.Service.ServiceController
class in order to see required services, PowerShell abstracts that complexity in the way it presents service objects to you.
Meet the ETS
Here's what I'm talking about. This is a typical PowerShell operation.
PS C:\> Get-Process -id $pid | Select-Object -Property ID,Name,WS,CommandLine,Product
Id : 35012
Name : pwsh
WS : 123248640
CommandLine : pwsh.exe -NoLogo -NoProfile
Product : PowerShell
Get something and display some properties. But where do these properties come from? Start by asking Get-Member
.
PS C:\> Get-Process -id $pid | Get-Member -Name ID,Name,WS,CommandLine,Product
TypeName: System.Diagnostics.Process
Name MemberType Definition
---- ---------- ----------
Id Property int Id {get;}
Name AliasProperty Name = ProcessName
WS AliasProperty WS = WorkingSet64
CommandLine ScriptProperty System.Object CommandLine {get=...
Product ScriptProperty System.Object Product {get=$this.Mainmodule.FileVersionInfo.Pr...
ID
is an actual property of the System.Diagnostics.Process
class. If you were to look up the documentation on this .NET class, you would find ID
as a property.However, you won't find the other properties listed. PowerShell added them to make working with process objects easier. The alias properties are defined so that you can useName
instead of ProcessName
and WS
instead of WorkingSet64
. A .NET developer would know to use ProcessName
and WorkingSet64
, but PowerShell abstracts that complexity for you and simplifies things so you can use Name
and WS
.
By the way, a script property is a way of getting a property value from a script block. The .NET class doesn't have a CommandLine
property. But PowerShell can run a code snippet to get a value. We'll dig into this in a bit.
All of these properties are added automatically by PowerShell's extensible type system (ETS). That's why you are encouraged to use Get-Member
to explore objects. Another way to discover if an object has been extended is to use Get-TypeData
. All you need to know is the object type name which you can get from Get-Member
.
PS C:\> $td = Get-TypeData System.Diagnostics.Process
PS C:\> $td.Members
Key Value
--- -----
Name System.Management.Automation.Runspaces.AliasPropertyData
SI System.Management.Automation.Runspaces.AliasPropertyData
Handles System.Management.Automation.Runspaces.AliasPropertyData
VM System.Management.Automation.Runspaces.AliasPropertyData
WS System.Management.Automation.Runspaces.AliasPropertyData
PM System.Management.Automation.Runspaces.AliasPropertyData
NPM System.Management.Automation.Runspaces.AliasPropertyData
Path System.Management.Automation.Runspaces.ScriptPropertyData
CommandLine System.Management.Automation.Runspaces.ScriptPropertyData
Parent System.Management.Automation.Runspaces.CodePropertyData
Company System.Management.Automation.Runspaces.ScriptPropertyData
CPU System.Management.Automation.Runspaces.ScriptPropertyData
FileVersion System.Management.Automation.Runspaces.ScriptPropertyData
ProductVersion System.Management.Automation.Runspaces.ScriptPropertyData
Description System.Management.Automation.Runspaces.ScriptPropertyData
Product System.Management.Automation.Runspaces.ScriptPropertyData
__NounName System.Management.Automation.Runspaces.NotePropertyData
This is a list of type extensions for process objects. The value indicates the type of property. Let's look at these with Get-Member
.
PS C:\> Get-Process -id $pid | Get-Member -name $($td.Members.keys)
TypeName: System.Diagnostics.Process
Name MemberType Definition
---- ---------- ----------
Name AliasProperty Name = ProcessName
SI AliasProperty SI = SessionId
Handles AliasProperty Handles = Handlecount
VM AliasProperty VM = VirtualMemorySize64
WS AliasProperty WS = WorkingSet64
PM AliasProperty PM = PagedMemorySize64
NPM AliasProperty NPM = NonpagedSystemMemorySize64
Path ScriptProperty System.Object Path {get=$this.Mainmodule.FileName…
CommandLine ScriptProperty System.Object CommandLine {get=…
Parent CodeProperty System.Object Parent{get=GetParentProcess;}
Company ScriptProperty System.Object Company {get=$this.Mainmodule.FileV…
CPU ScriptProperty System.Object CPU {get=$this.TotalProcessorTime.T…
FileVersion ScriptProperty System.Object FileVersion {get=$this.Mainmodule.F…
ProductVersion ScriptProperty System.Object ProductVersion {get=$this.Mainmodul…
Description ScriptProperty System.Object Description {get=$this.Mainmodule.F…
Product ScriptProperty System.Object Product {get=$this.Mainmodule.FileV…
__NounName NoteProperty string __NounName=Process
A CodeProperty
is similar to a ScriptProperty
, except that the value is derived from invoking compiled code. A NoteProperty
is a simple property that typically has a fixed value for all objects.
PS C:\> Get-Process | Get-Random -count 5 |
Select-Object -Property ID,Name,__NounName
Id Name __NounName
-- ---- ----------
6088 pia-service Process
12392 vmmem Process
27216 wsl Process
21056 Code Process
17532 IntelSoftwareAssetManagerService Process