MMS in San Diego was a great conference! I met lots of customers that asked lots of great questions. I was demonstrating PowerShell’s WMI support when a customer asked about controlling the output. The problem was that PowerShell was showing all the WMI System properties as well as the Object properties and that this wasn’t what they wanted. PowerShell makes WMI objects look like any other object so there is no “special” processing for WMI so the question is, can you do the equivalent of -EXCLUDE __* (All WMI System Properties start with “__”). Let me illustrate the problem:
PS> Get-WmiObject Win32_Processor
AddressWidth : 32
Architecture : 0
Availability : 3
Caption : x86 Family 6 Model 13 Stepping 8
ConfigManagerErrorCode :
ConfigManagerUserConfig :
CpuStatus : 1
CreationClassName : Win32_Processor
CurrentClockSpeed : 786
CurrentVoltage : 33
DataWidth : 32
Description : x86 Family 6 Model 13 Stepping 8
DeviceID : CPU0
ErrorCleared :
ErrorDescription :
ExtClock : 133
Family : 2
InstallDate :
L2CacheSize : 2048
L2CacheSpeed :
LastErrorCode :
Level : 6
LoadPercentage : 0
Manufacturer : GenuineIntel
MaxClockSpeed : 2127
Name : Intel(R) Pentium(R) M processor 2.13GHz
OtherFamilyDescription :
PNPDeviceID :
PowerManagementCapabilities :
PowerManagementSupported : False
ProcessorId : AFE9FBFF000006D8
ProcessorType : 3
Revision : 3336
Role : CPU
SocketDesignation : Microprocessor
Status : OK
StatusInfo : 3
Stepping : 8
SystemCreationClassName : Win32_ComputerSystem
SystemName : JPSLAP04
UniqueId :
UpgradeMethod : 6
Version : Model 13, Stepping 8
VoltageCaps : 2
__GENUS : 2
__CLASS : Win32_Processor
__SUPERCLASS : CIM_Processor
__DYNASTY : CIM_ManagedSystemElement
__RELPATH : Win32_Processor.DeviceID=”CPU0″
__PROPERTY_COUNT : 44
__DERIVATION : {CIM_Processor, CIM_LogicalDevice, CIM_LogicalElement, CIM_ManagedSystemElement}
__SERVER : JPSLAP04
__NAMESPACE : root\cimv2
__PATH : \\JPSLAP04\root\cimv2:Win32_Processor.DeviceID=”CPU0“
The last 10 properties are all system properties. In this example, it is annoying but not horrible to include the system properties but now consider this example:
PS> Get-WmiObject Win32_Processor -property Name
Name : Intel(R) Pentium(R) M processor 2.13GHz
__GENUS : 2
__CLASS : Win32_Processor
__SUPERCLASS :
__DYNASTY :
__RELPATH :
__PROPERTY_COUNT : 1
__DERIVATION : {}
__SERVER :
__NAMESPACE :
__PATH :
The system properties are always included, even if you just get a single property. So the ability to say
Get-WmiObject Win32_Processor -property Name |fl -Exclude __*
would be great. We LOVE -Exclude (applied LOTS of places) and the ony reason it isn’t more places in V1 is simply a “to ship is to choose” issue. Soooo, it was with great sadness that I had to give this customer the world’s worse answer: We plan to provide this in the next release, hang in there for a few years and things will get better.
I want to pull my hair out every time I have to say that. One of the whole points of PowerShell was to avoid ever having this conversation. The idea was that feature team would expose their mgmt via PowerShell and then delivers their “scenarios” on top of that (like Exchange 2007 has done). Then when a customer says that the scenario doesn’t meet their needs, the feature team can say, “Great – we’ll fix that in our next release but in the meantime, you can get that using the following script”. NIRVANA.
So when I had to say this myself – it really hurt. We’ve put quite a bit of energy into designing PowerShell to be dynamically extensible (e.g. our extensible type system and formatting system) but there will always be things that require changes to the engine.
Back to the question – my full answer was that -Exclude would come in a future release but that the right way to do this was to define a custom formatting VIEW for this object. We extend WMI objects in a way that allow you to register Views for them.
PS> @(get-wmiobject -class “Win32_Share”)[0].PSTypeNames
System.Management.ManagementObject#root\cimv2\Win32_Share
System.Management.ManagementObject
System.Management.ManagementBaseObject
System.ComponentModel.Component
System.MarshalByRefObject
System.Object
This is the data that is used for all of PowerShell’s type extensions and formatting decisions. Notice the first entry. In .NET, a single class (System.Management.ManagementObject) represents all WMI instances so it would be impossible to register meaningful extensions if we just had that. This is why we add an entry extending the .NET hierarchy with a synthetic entry which uses the WMI ClassPath. Now you can define a view like this:
<Configuration>
<ViewDefinitions>
<View>
<Name>CustomView</Name>
<ViewSelectedBy>
<TypeName>System.Management.ManagementObject</TypeName>
</ViewSelectedBy>
<TableControl>
<TableHeaders>
<TableColumnHeader>
<Label>Name</Label>
<Width>12</Width>
</TableColumnHeader>
<TableColumnHeader>
<Label>Description</Label>
<Width>30</Width>
</TableColumnHeader>
<TableColumnHeader>
<Label>Path</Label>
</TableColumnHeader>
</TableHeaders>
<TableRowEntries>
<TableRowEntry>
<TableColumnItems>
<TableColumnItem>
<PropertyName>Name</PropertyName>
</TableColumnItem>
<TableColumnItem>
<PropertyName>Description</PropertyName>
</TableColumnItem>
<TableColumnItem>
<PropertyName>Path</PropertyName>
</TableColumnItem>
</TableColumnItems>
</TableRowEntry>
</TableRowEntries>
</TableControl>
</View>
</ViewDefinitions>
</Configuration>
Put this in a file like Win32_Share.Format.PS1xml and execute the command Update-FormatData Win32_Share.Format.PS1xml and the then you can do this:
PS> Get-WmiObject -Class Win32_Share
Name Description Path
—- ———– —-
E$ Default share E:\
IPC$ Remote IPC
CCMSetup$ Microsoft IT SMS Troublesho… C:\WINDOWS\system…
VPCache$ Microsoft IT SMS Troublesho… C:\WINDOWS\system…
ps C:\ps
WMILogs$ Microsoft IT SMS Troublesho… C:\WINDOWS\system…
CCMLogs$ Microsoft IT SMS Troublesho… C:\WINDOWS\system…
ADMIN$ Remote Admin C:\WINDOWS
C$ Default share C:\
So we’ve got a reasonable answer but I still wanted to give the customer a way to get what he wanted. On the flight back home, it hit me – you can use wildcards in formatting to solve this problem. When you pipe objects to our formatters you can specify which properties you want to show. e.g.
get-process |FT ID,Handles
Here I’ve specified that I want to properties whose Names are ID and Handles to be output. But here is the BIG deal: you are NOT limited to specifying property NAMES you can specify any or all of the following things:
PropertySets: PropertySets are named sets of properties that you can define as part of our extended type system. We’ve define a few for you. Here is an example of that working:
PS> gps |gm -membertype PropertySet
TypeName: System.Diagnostics.Process
Name MemberType Definition
—- ———- ———-
PSConfiguration PropertySet PSConfiguration {Name, Id, PriorityCla…
PSResources PropertySet PSResources {Name, Id, Handlecount, Wo…
PS> gps |ft PSConfiguration
Name Id PriorityClass FileVersion
—- — ————- ———–
AcroRd32 1360 Normal 7.0.5.2005092300
alg 2356 Normal 5.1.2600.2180…
apdproxy 1964 Normal 3.0.0.49815
ApntEx 3996 Normal 5.5.1.19
…
Expressions – you can specify a scriptblock and the system will assign the current object to the variable $_ ,execute the scriptblock and use the result:
PS> gps i* |ft name,{$_.StartTime.dayofweek}
Name $_.StartTime.dayofweek
—- ———————-
Idle
iexplore Saturday
iexplore Saturday
iexplore Saturday
InoRpc Thursday
InoRT Thursday
InoTask Thursday
HashTables – you can specify a hashtable with the following Keys: Label, Expression, Alignment, Width. The formatter will use these to drive its processing:
PS> gps i* |ft name,@{Label=”WeekDay”;Expression={$_.StartTime.DayOfWeek};Width=60}
Name WeekDay
—- ——-
Idle
iexplore Saturday
iexplore Saturday
iexplore Saturday
InoRpc Thursday
InoRT Thursday
InoTask Thursday
WildCards – you can specify a set of propertynames using wildcards!
PS> gps i* |ft name,pe*64
Name PeakPagedMemorySi PeakWorkingSet64 PeakVirtualMemor
ze64 ySize64
—- —————– —————- —————-
Idle 0 0 0
iexplore 114106368 117862400 270757888
iexplore 118153216 131960832 278261760
iexplore 119189504 131948544 273432576
InoRpc 5140480 8220672 75395072
InoRT 17981440 20332544 76890112
InoTask 11993088 15597568 72310784
you can specify a set of propertynames using wildcards! So now the question is, how do wildcards help with the WMI issue? By specifying properties [a-z]* , you’ll get all properties which start with an A-Z but none of those that start with __ .
PS> Get-WmiObject Win32_Processor |fl [a-z]*
AddressWidth : 32
Architecture : 0
Availability : 3
Caption : x86 Family 6 Model 13 Stepping 8
ConfigManagerErrorCode :
ConfigManagerUserConfig :
CpuStatus : 1
CreationClassName : Win32_Processor
CurrentClockSpeed : 786
CurrentVoltage : 33
DataWidth : 32
Description : x86 Family 6 Model 13 Stepping 8
DeviceID : CPU0
ErrorCleared :
ErrorDescription :
ExtClock : 133
Family : 2
InstallDate :
L2CacheSize : 2048
L2CacheSpeed :
LastErrorCode :
Level : 6
LoadPercentage : 0
Manufacturer : GenuineIntel
MaxClockSpeed : 2127
Name : Intel(R) Pentium(R) M processor
2.13GHz
OtherFamilyDescription :
PNPDeviceID :
PowerManagementCapabilities :
PowerManagementSupported : False
ProcessorId : AFE9FBFF000006D8
ProcessorType : 3
Revision : 3336
Role : CPU
SocketDesignation : Microprocessor
Status : OK
StatusInfo : 3
Stepping : 8
SystemCreationClassName : Win32_ComputerSystem
SystemName : JPSLAP04
UniqueId :
UpgradeMethod : 6
Version : Model 13, Stepping 8
VoltageCaps : 2
So there, you don’t have to hang in there a few years before we get around to implementing this. We still need to implement it because there are times when this will be the best way to think about the problem but at least for this scenario, you are not blocked.
Our formatting and outputing system is quite powerful and it will really pay off to spend a some time exploring it’s capabilities. I think you’ll be quite surprised and pleased by the things you can do. It is not as rich as we want it (and we are very interested in hearing what additional features you want from it) but it is still a pretty amazing V1.
Enjoy!
Jeffrey Snover
PowerShell Architect
PSMDTAG:TYPE:WMI formatting, synthetic types
PSMDTAG:CMDLET:FORMAT propertysets, expressions, hashtables, wildcards
PSMDTAG:INTERNAL Type->Synthetic Type->Formatting
PSMDTAG:FORMATEXTENSION:ManagementObject
0 comments