if you type GET-PROCESS what will be the output ?
1: Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
2: ------- ------ ----- ----- ----- ------ -- -----------
3: 32 5 1004 2908 29 1.11 2620 conhost
4: 734 13 2448 4176 51 6.88 416 csrss
5: 660 14 3044 7376 63 123.70 480 csrss
As we can see the properties displayed are Handles,NPM(K),PM(K),WS(K),VM(K),CPU(s),Id and ProcessName.
Ok..now type GET-PROCESS | SELECT * : (LIST1 – All properties from Get-Process)
1:
2: __NounName : Process
3: Name : WmiPrvSE
4: Handles : 343
5: VM : 200318976
6: WS : 29708288
7: PM : 18628608
8: NPM : 22536
9: Path : C:\Windows\system32\wbem\wmiprvse.exe
10: Company : Microsoft Corporation
11: CPU : 7694.421875
12: FileVersion : 6.1.7601.17514 (win7sp1_rtm.101119-1850)
13: ProductVersion : 6.1.7601.17514
14: Description : WMI Provider Host
15: Product : Microsoft® Windows® Operating System
16: Id : 3060
17: PriorityClass : Normal
18: HandleCount : 343
19: WorkingSet : 29708288
20: PagedMemorySize : 18628608
21: PrivateMemorySize : 18628608
22: VirtualMemorySize : 200318976
23: TotalProcessorTime : 02:08:14.4218750
24: BasePriority : 8
25: ExitCode :
26: HasExited : False
27: ExitTime :
28: Handle : 3636
29: MachineName : .
30: MainWindowHandle : 0
31: MainWindowTitle :
32: MainModule : System.Diagnostics.ProcessModule (wmiprvse.exe)
33: MaxWorkingSet : 1413120
34: MinWorkingSet : 204800
35: Modules : {System.Diagnostics.ProcessModule (wmiprvse.exe), System.Diagnostics.ProcessModule (ntdll.dll),
36: System.Diagnostics.ProcessModule (kernel32.dll), System.Diagnostics.ProcessModule (KERNELBASE.
37: dll)...}
38: NonpagedSystemMemorySize : 22536
39: NonpagedSystemMemorySize64 : 22536
40: PagedMemorySize64 : 18628608
41: PagedSystemMemorySize : 164304
42: PagedSystemMemorySize64 : 164304
43: PeakPagedMemorySize : 101957632
44: PeakPagedMemorySize64 : 101957632
45: PeakWorkingSet : 108654592
46: PeakWorkingSet64 : 108654592
47: PeakVirtualMemorySize : -1339703296
48: PeakVirtualMemorySize64 : 2955264000
49: PriorityBoostEnabled : True
50: PrivateMemorySize64 : 18628608
51: PrivilegedProcessorTime : 00:53:47.2968750
52: ProcessName : WmiPrvSE
53: ProcessorAffinity : 3
54: Responding : True
55: SessionId : 0
56: StartInfo : System.Diagnostics.ProcessStartInfo
57: StartTime : 8/8/2012 8:42:06 PM
58: SynchronizingObject :
59: Threads : {2844, 2512, 2584, 680...}
60: UserProcessorTime : 01:14:27.1250000
61: VirtualMemorySize64 : 200318976
62: EnableRaisingEvents : False
63: StandardInput :
64: StandardOutput :
65: StandardError :
66: WorkingSet64 : 29708288
67: Site :
68: Container :
WOHOOOO !!!! Why if I type GET-PROCESS the output is different from GET-PROCESS | Select * ?
Because the default properties set up in a Windows PowerShell Formatting File, or a file with extension FORMAT.PS1XML, that are stored , IN THE CASE OF GET-PROCESS, on the PowerShell install folder.
How it works ? Generally speaking, because there is a LOT of configuration that you can do in a formatting file, PowerShell uses a LOT of formatting files to format the default display for a .NET Framework Objects. This means that you can choose what default properties to display, how to display, where (position)to display and you can create formulas too, using a node in the XML called <scriptblock>. In the case of GET-PROCESS the property PM(K) , is first displayed with a label PM(K) – You can see in the list above that does not exist any property called PM(K) -That is a formula in the DotNetTypes.format.ps1xml:
<ScriptBlock>[int]($_.PM / 1024)</ScriptBlock>
Now if you take a look on the LIST1 above we have a property called PM
__NounName : Process
Name : WmiPrvSE
Handles : 258
VM : 94494720
WS : 31690752
PM : 25993216
NPM : 18128
Path : C:\Windows\system32\wbem\wmiprvse.exe
and this property is part of the formula in the DotNetTypes.format.ps1xml
How do I know this ? The output type from GET-PROCESS is a System.Diagnostics.Process (GET-PROCESS | GM), and if you search on DotNetTypes.format.ps1xml for this type you will find out all the information:
<View>
<Name>process</Name>
<ViewSelectedBy>
<TypeName>System.Diagnostics.Process</TypeName>
</ViewSelectedBy>
<TableControl>
<TableHeaders>
<TableColumnHeader>
<Label>Handles</Label>
<Width>7</Width>
<Alignment>right</Alignment>
</TableColumnHeader>
<TableColumnHeader>
<Label>NPM(K)</Label>
<Width>7</Width>
<Alignment>right</Alignment>
</TableColumnHeader>
<TableColumnHeader>
<Label>PM(K)</Label>
<Width>8</Width>
<Alignment>right</Alignment>
</TableColumnHeader>
<TableColumnHeader>
<Label>WS(K)</Label>
<Width>10</Width>
<Alignment>right</Alignment>
</TableColumnHeader>
<TableColumnHeader>
<Label>VM(M)</Label>
<Width>5</Width>
<Alignment>right</Alignment>
</TableColumnHeader>
<TableColumnHeader>
<Label>CPU(s)</Label>
<Width>8</Width>
<Alignment>right</Alignment>
</TableColumnHeader>
<TableColumnHeader>
<Width>6</Width>
<Alignment>right</Alignment>
</TableColumnHeader>
<TableColumnHeader />
</TableHeaders>
<TableRowEntries>
<TableRowEntry>
<TableColumnItems>
<TableColumnItem>
<PropertyName>HandleCount</PropertyName>
</TableColumnItem>
<TableColumnItem>
<ScriptBlock>[int]($_.NPM / 1024)</ScriptBlock>
</TableColumnItem>
<TableColumnItem>
<ScriptBlock>[int]($_.PM / 1024)</ScriptBlock>
</TableColumnItem>
<TableColumnItem>
<ScriptBlock>[int]($_.WS / 1024)</ScriptBlock>
</TableColumnItem>
<TableColumnItem>
<ScriptBlock>[int]($_.VM / 1048576)</ScriptBlock>
</TableColumnItem>
<TableColumnItem>
<ScriptBlock>
_.CPU -ne $())
{
_.CPU.ToString("N")
}
</ScriptBlock>
</TableColumnItem>
<TableColumnItem>
<PropertyName>Id</PropertyName>
</TableColumnItem>
<TableColumnItem>
<PropertyName>ProcessName</PropertyName>
</TableColumnItem>
</TableColumnItems>
</TableRowEntry>
</TableRowEntries>
</TableControl>
</View>
<View>
You can find a complete list of the Formatting Files in Windows PowerShell Formatting Files. In this guide it says :
Windows PowerShell provides several formatting files (.format.ps1xml) that are located in the installation directory (
$pshome). Each of these files defines the default display for a specific set of .NET Framework objects. These files should never be changed. However, you can use them as a reference for creating your own custom formatting files.
Hummmmm..Ok..then..I can create formatting files to my functions![]()
I have a function called GET-SQLServerInfo. The code is pretty simple and it is to display all information about SQL Server using SMO :
Function Get-SqlServerInfo {
[CmdletBinding()]
param(
[Parameter(Position=0, Mandatory=$true, ValueFromPipeline = $true)] [string[]]$SQLServer
)
begin {
[reflection.assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo") > $null
}
process {
foreach ($SQL in $SQLServer) {
$server = new-object ('Microsoft.SqlServer.Management.Smo.Server') $SQL
write-output $server
}
}
}
The problem it is exactly what I said. It display ALL information about an SQL Server Instance. Besides it is slowly, sometimes I just want some basic properties.
There is some ways to do this:
- I can create a PSCustomObject and output only what I want.
- I can pipe to Select-Object and show only what I want.
Problems :
Solution 1 – If I want the other properties….I do need to create other function (That would be out of the question.)
Solution 2 – I can do that. But Would not it be nice to have formatted the output with only a few basic properties and if I want to show the rest I just pipe to Select-Object * ?
Then, there is a 3 solution. Create a Formatting File to that. A formatting file is associated to the type of the object , not to an specific function, as we saw to GEt-PROCESS and the type System.Diagnostics.Process. If you type Get-FormatData you will see the object types and its formats :
How Can I Find the relationship between a formatting file and the object type ? I found in this blog a cool function to do that. In this case he is using only to Get-EventLog and Get-WinEvent, but you can change to the function that you want ![]()
Powershell Objects and .PS1XML Files
Now, Lets back to our example : My function GET-SQLServerInfo output a object type Microsoft.SqlServer.Management.Smo.Server, then it is just to start to create the formatting file, in my case,Functions.Format.ps1xml. to display by default the properties and its label and width :
| Description | Label | Width | Property |
| SQL Server Instance Name | Name | 15 | Name |
| SQL Server Edition | Edition | 30 | Edition |
| SQL Server Product Level | Product Level | 15 | ProductLevel |
| SQL Server Version | Version | 22 | Scriptblock : $_.Version.ToString() |
| SQL Server Collation | Collation | 40 | Collation |
The Functions.Format.ps1xml is :
<Configuration>
<ViewDefinitions>
<View>
<Name>Table</Name>
<ViewSelectedBy>
<TypeName>Microsoft.SqlServer.Management.Smo.Server</TypeName>
</ViewSelectedBy>
<TableControl>
<TableHeaders>
<TableColumnHeader>
<Label>Name</Label>
<Width>15</Width>
<Alignment>left</Alignment>
</TableColumnHeader>
<TableColumnHeader>
<Label>Edition</Label>
<Width>30</Width>
<Alignment>left</Alignment>
</TableColumnHeader>
<TableColumnHeader>
<Label>Product Level</Label>
<Width>15</Width>
<Alignment>left</Alignment>
</TableColumnHeader>
<TableColumnHeader>
<Label>Version</Label>
<Width>22</Width>
<Alignment>left</Alignment>
</TableColumnHeader>
<TableColumnHeader>
<Label>Collation</Label>
<Width>40</Width>
<Alignment>left</Alignment>
</TableColumnHeader>
</TableHeaders>
<TableRowEntries>
<TableRowEntry>
<Wrap/>
<TableColumnItems>
<TableColumnItem>
<PropertyName>Name</PropertyName>
</TableColumnItem>
<TableColumnItem>
<PropertyName>Edition</PropertyName>
</TableColumnItem>
<TableColumnItem>
<PropertyName>ProductLevel</PropertyName>
</TableColumnItem>
<TableColumnItem>
<ScriptBlock>$_.Version.ToString()</ScriptBlock>
</TableColumnItem>
<TableColumnItem>
<PropertyName>Collation</PropertyName>
</TableColumnItem>
</TableColumnItems>
</TableRowEntry>
</TableRowEntries>
</TableControl>
</View>
</ViewDefinitions>
</Configuration>
I save the formatting file in the $PSHOME folder . To load the file I can do it in the current session using Update-Formatdata cmdlet :
Update-formatdata –prependpath "$($PSHOME)\Functions.Format.ps1xml"
or , an better, create or add in my module manifest from this module and in the FormatsToProcess option associate with Functions.Format.ps1xml . This way I moved the file to the Functions Folder and in this folder now I have 3 files. Functions.psm1, Functions.psd1 and Functions.Format.ps1xml
Then when I start a PowerShell session my module will be loaded with its formatting file . If I type GET-SQLServerInfo :
Get-SqlServerInfo r2d2
Name Edition Product Level Version Collation
---- ------- ------------- ------- ---------
r2d2 Enterprise Edition (64-bit) RTM 11.0.2100 SQL_Latin1_General_CP1_CI_AS
It is faster because I am only loading 5 properties and if I want to show all properties , it is just pipe to SELECT-OBJECT * :
Get-SqlServerInfo r2d2 | select *
Cool !!! uh ? To read :
Writing a Windows PowerShell Formatting File
How to Write a Module Manifest
#PowerShellLifeStyle



