WMI and CIM accelerators

In PowerShell an accelerator is a shortcut to a .NET type. The WMI accelerators have been around since PowerShell v1. The WMI accelerators were heavily used in v1 fill some of the gaps in cmdlet coverage. The CIM accelerators appeared in PowerShell v3 (I think – only discovered them recently!). This is how you use the WMI and CIM accelerators.

There are three WMI accelerators

wmiclass is shortcut for System.Management.ManagementClass
wmi is shortcut for System.Management.ManagementObject
wmisearcher is shortcut for System.Management.ManagementObjectSearcher

And four CIM accelerators are

ciminstance is shortcut for Microsoft.Management.Infrastructure.CimInstance
cimclass is shortcut for Microsoft.Management.Infrastructure.CimClass
cimtype is shortcut for Microsoft.Management.Infrastructure.CimType
cimconverter is shortcut for Microsoft.Management.Infrastructure.CimConverter

plus

CimSession  which is a shortcut for                 Microsoft.Management.Infrastructure.CimSession. Use this to set a parameter type.

Notice that there isn’t a direct correspondence between the WMI and CIM accelerators.

PowerShell v6 only has the CIM accelerators

The WMI accelerators are used like this:

WMICLASS

This can be used for creating new instances of CIM classes

PS> $p = [wmiclass]’Win32_Process’
PS> $p.Create(“notepad.exe”)

This is easily replicated using the CIM cmdlets

PS> Invoke-CimMethod -ClassName Win32_Process -MethodName create -Arguments @{CommandLine=’notepad.exe’}

WMI

The [wmi] accelerator is used to find an instance BUT you have to use the class key!

PS> [wmi]”root\cimv2:Win32_Process.Handle=’7264′”

NOTE the handle has to be the one reported by CIM NOT the one reported by Get-Process!

Its much easier to use Get-CimInstance and filter on the name

Get-CimInstance -ClassName Win32_Process -Filter “Name=’pwsh.exe'”

WMISEARCHER

This is used to find CIM instances:

PS> $query = [wmisearcher]”SELECT * FROM Win32_Process WHERE Name=’pwsh.exe'”
PS> $query.Get()

Its easier to use Get-CIMinstance these days

PS> Get-CimInstance -ClassName Win32_Process -Filter “Name=’pwsh.exe'”

Looking at the CIM accelerators

CIMINSTANCE

This one doesn’t seem to be usable for anything but a type decorator on a parameter.

CIMCLASS

Using Get-CimClass

PS> Get-CimClass -ClassName Win32_process | fl

CimSuperClassName   : CIM_Process
CimSuperClass       : ROOT/cimv2:CIM_Process
CimClassProperties  : {Caption, Description, InstallDate, Name…}
CimClassQualifiers  : {Locale, UUID, CreateBy, DeleteBy…}
CimClassMethods     : {Create, Terminate, GetOwner, GetOwnerSid…}
CimSystemProperties : Microsoft.Management.Infrastructure.CimSystemProperties
CimClassName        : Win32_Process

The output is of type Microsoft.Management.Infrastructure.CimClass for which cimclass  is an accelerator BUT there doesn’t seem to be a way to use the accelerator to access a class. I think this one is only usable as a type on a parameter for a function where you want to pass in a CIM class object.

CIMTYPE

Microsoft.Management.Infrastructure.CimType is an enum that contains the CIM (and WMI) datatypes:

PS> [cimtype]::Boolean
Boolean
PS> [cimtype]::UInt32
UInt32

The full set of CIM data types is

PS> [enum]::GetNames([cimtype])
Unknown
Boolean
UInt8
SInt8
UInt16
SInt16
UInt32
SInt32
UInt64
SInt64
Real32
Real64
Char16
DateTime
String
Reference
Instance
BooleanArray
UInt8Array
SInt8Array
UInt16Array
SInt16Array
UInt32Array
SInt32Array
UInt64Array
SInt64Array
Real32Array
Real64Array
Char16Array
DateTimeArray
StringArray
ReferenceArray
InstanceArray

CIMCONVERTOR

Some of the CIM data types shown above don’t directly correspond to .NET types you’re used to from PowerShell. You can use [cimconvertor] which is shortcut for Microsoft.Management.Infrastructure.CimConverter to discover the corresponding .NET or CIM data type

.NET to CIM

PS> [cimconverter]::GetCimType([int32])
SInt32
PS> [cimconverter]::GetCimType([double])
Real64

CIM to .NET

PS> [cimconverter]::GetDotNetType([cimtype]::SInt32)

IsPublic IsSerial Name                                     BaseType
——– ——– —-                                     ——–
True     True     Int32                                    System.ValueType

PS> [cimconverter]::GetDotNetType([cimtype]::Instance)

IsPublic IsSerial Name                                     BaseType
——– ——– —-                                     ——–
True     True     CimInstance                              System.Object

For the most part I think the WMI and CIM accelerators are best ignored. Use the CIM cmdlets instead. The cimtype and cimconverter accelerators are useful when developing code to check on types between CIM and .NET

Advertisements
Posted in PowerShell and CIM, PowerShell and WMI | Leave a comment

PowerShell parameter sets

PowerShell parameter sets allow you to control which parameters can be used together. If a parameter isn’t in the parameter set you’re trying to use you’ll get an error message.

PS> Get-VM -Name XYZ -id (New-Guid)
Get-VM : Parameter set cannot be resolved using the specified named parameters.

At line:1 char:1
 + Get-VM -Name XYZ -id (New-Guid)

+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 + CategoryInfo          : InvalidArgument: (:) [Get-VM], ParameterBindingException
 + FullyQualifiedErrorId : AmbiguousParameterSet,Microsoft.HyperV.PowerShell.Commands.GetVM

You can also use parameter sets to help control the processing within your function as this example shows:

function Convert-Temperature {
param (
[Parameter(ParameterSetName='Celsius')]
[double]$degreeC,

[Parameter(ParameterSetName='Fahrenheit')]
[double]$degreeF,

[Parameter(ParameterSetName='Kelvin')]
[double]$degreeK
)

$temps = New-Object -TypeName psobject -Property @{
'Temperature-Celsius' = 0.0
'Temperature-Fahrenheit' = 0.0
'Temperature-Kelvin' = 0.0
}

switch ($psCmdlet.ParameterSetName) {
"Celsius" {
$temps.'Temperature-Celsius' = $degreeC
$temps.'Temperature-Fahrenheit' = [math]::Round((32 + ($degreeC * 1.8)), 2)
$temps.'Temperature-Kelvin' = $degreeC + 273.15
}

"Fahrenheit" {
$temps.'Temperature-Celsius' = [math]::Round((($degreeF - 32) / 1.8), 2)
$temps.'Temperature-Fahrenheit' = $degreeF
$temps.'Temperature-Kelvin' = $temps.'Temperature-Celsius' + 273.15
}

"Kelvin" {
$temps.'Temperature-Celsius' = $degreeK - 273.15
$temps.'Temperature-Fahrenheit' = [math]::Round((32 + ($temps.'Temperature-Celsius' * 1.8)), 2)
$temps.'Temperature-Kelvin' = $degreeK
}

default {Write-Error -Message "Error!!! Should not be here" }
}

$temps
}

Each of the input parameters is in its own parameter set meaning that they are mutually exclusive – you can only use one of them!

The switch statement uses the active parameter set name to decide how to perform the relevant conversions – the output object contains the temperature in Celsius, Fahrenheit and Kelvin

Posted in Powershell | Leave a comment

PowerShell version

Discovering the PowerShell version you’re using can be an interesting task.

The automatic variable $PSVersionTable was introduced in PowerShell v2.  On my Windows 10 version 1803 machine for Windows PowerShell I get

PS> $PSVersionTable

Name                           Value
—-                           —–
PSVersion                      5.1.17134.48
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
BuildVersion                   10.0.17134.48
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1

$PSVersionTable is a hashtable so the order in which items are displayed may vary. The contents of the hashtable have changed over time as well.

The important parts of $PsversionTable include:

The version of PowerShell itself

PS> $PSVersionTable.PSVersion

Major  Minor  Build  Revision
—–  —–  —–  ——–
5      1      17134  48

PS> $PSVersionTable.PSVersion.Major
5

This a simple test for version.

The edition is also important

PS> $PSVersionTable.PSEdition
Desktop

Desktop means its full CLR – in other words Windows PowerShell

The WSMAN version is also important

PS> $PSVersionTable.WSManStackVersion

Major  Minor  Build  Revision
—–  —–  —–  ——–
3      0      -1     -1

You need v3 to use CIM sessions.

With PowerShell v6 you get a few more options

PS>  $PSVersionTable

Name                           Value
—-                           —–
PSVersion                      6.0.1
PSEdition                      Core
GitCommitId                    v6.0.1
OS                             Microsoft Windows 10.0.17134
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

Notice PSEdition is set to Core.

The OS and Platform data are v6 only

The PSRemotingProtocolVersion, SerializationVersion and WSManStackVersion are the same for Windows PowerShell v5.1 and PowerShell v6.

PowerShell v6 runs on Windows, Linux and macOS. You can test which OS you’re on from $PSVersionTable or more simply using the following automatic variables:

PS>  ls variable:\is*

Name                           Value
—-                           —–
IsLinux                        False
IsMacOS                        False
IsWindows                      True
IsCoreCLR                      True

Using these you could create branching logic to perform a task by calling the appropriate command based on the underlying operating system.

Posted in PowerShell v5, PowerShell v6 | Leave a comment

Format Data

PowerShell will format the output of objects that it knows about.  For instance Get-Process shows different sets of properties depending on whether  you choose a table or list view. The format data is stored in files named *.format.ps1xml.

In Windows PowerShell the format files are found in C:\Windows\System32\WindowsPowerShell\v1.0. In PowerShell v6 the format files are stored with the appropriate module.

If you want to create formatting for a new object, or change the formatting for an existing object the best place to start is to export the format data for an existing object

Get-FormatData -TypeName System.Diagnostics.Process | Export-FormatData -Path f5.txt

gets the format data for the object used in Get-Process.

The drawback is that is presented a long string

<?xml version=”1.0″ encoding=”utf-8″?><Configuration><ViewDefinitions><View><Name>process</Name><ViewSelectedBy><TypeNam
e>System.Diagnostics.Process</TypeName></ViewSelectedBy><TableControl><TableHeaders><TableColumnHeader><Label>Handles</L
abel><Width>7</Width><Alignment>Right</Alignment></TableColumnHeader><TableColumnHeader><Label>NPM(K)</Label><Width>7</W
idth><Alignment>Right</Alignment></TableColumnHeader><TableColumnHeader><Label>PM(K)</Label><Width>8</Width><Alignment>R
ight</Alignment></TableColumnHeader><TableColumnHeader><Label>WS(K)</Label><Width>10</Width><Alignment>Right</Alignment>
</TableColumnHeader><TableColumnHeader><Label>CPU(s)</Label><Width>10</Width><Alignment>Right</Alignment></TableColumnHe
ader><TableColumnHeader><Width>6</Width><Alignment>Right</Alignment></TableColumnHeader><TableColumnHeader><Width>3</Wid
th><Alignment>Right</Alignment></TableColumnHeader><TableColumnHeader /></TableHeaders><TableRowEntries><TableRowEntry><
TableColumnItems><TableColumnItem><PropertyName>HandleCount</PropertyName></TableColumnItem><TableColumnItem><ScriptBloc
k>;</ScriptBlock></TableColumnItem><TableColumnItem><ScriptBlock>;</ScriptBlock></TableColumnItem><TableColumnItem><Scri
ptBlock>;</ScriptBlock></TableColumnItem><TableColumnItem><ScriptBlock>;</ScriptBlock></TableColumnItem><TableColumnItem
><PropertyName>Id</PropertyName></TableColumnItem><TableColumnItem><PropertyName>SI</PropertyName></TableColumnItem><Tab
leColumnItem><PropertyName>ProcessName</PropertyName></TableColumnItem></TableColumnItems></TableRowEntry></TableRowEntr
ies></TableControl></View><View><Name>process</Name><ViewSelectedBy><TypeName>System.Diagnostics.Process</TypeName></Vie
wSelectedBy><WideControl><WideEntries><WideEntry><WideItem><PropertyName>ProcessName</PropertyName></WideItem></WideEntr
y></WideEntries></WideControl></View></ViewDefinitions></Configuration>

And you have to manage the pretty printing yourself.

In PowerShell v6.1 the output is automatically pretty printed

Get-FormatData -TypeName System.Diagnostics.Process | Export-FormatData -Path f6.txt

<?xml version=”1.0″ encoding=”utf-8″?>
<Configuration>
   <ViewDefinitions>
     <View>
       <Name>process</Name>
       <ViewSelectedBy>
         <TypeName>System.Diagnostics.Process</TypeName>
       </ViewSelectedBy>
       <TableControl>
         <TableHeaders>
           <TableColumnHeader>
             <Label>NPM(K)</Label>
             <Width>7</Width>
             <Alignment>Right</Alignment>
           </TableColumnHeader>
           <TableColumnHeader>
             <Label>PM(M)</Label>
             <Width>8</Width>
             <Alignment>Right</Alignment>
           </TableColumnHeader>
           <TableColumnHeader>
             <Label>WS(M)</Label>
             <Width>10</Width>
             <Alignment>Right</Alignment>
           </TableColumnHeader>
           <TableColumnHeader>
             <Label>CPU(s)</Label>
             <Width>10</Width>
             <Alignment>Right</Alignment>
           </TableColumnHeader>
           <TableColumnHeader>
             <Width>7</Width>
             <Alignment>Right</Alignment>
           </TableColumnHeader>
           <TableColumnHeader>
             <Width>3</Width>
             <Alignment>Right</Alignment>
           </TableColumnHeader>
           <TableColumnHeader />
         </TableHeaders>
         <TableRowEntries>
           <TableRowEntry>
             <TableColumnItems>
               <TableColumnItem>
                 <ScriptBlock>;</ScriptBlock>
               </TableColumnItem>
               <TableColumnItem>
                 <ScriptBlock>;</ScriptBlock>
               </TableColumnItem>
               <TableColumnItem>
                 <ScriptBlock>;</ScriptBlock>
               </TableColumnItem>
               <TableColumnItem>
                 <ScriptBlock>;</ScriptBlock>
               </TableColumnItem>
               <TableColumnItem>
                 <PropertyName>Id</PropertyName>
               </TableColumnItem>
               <TableColumnItem>
                 <PropertyName>SI</PropertyName>
               </TableColumnItem>
               <TableColumnItem>
                 <PropertyName>ProcessName</PropertyName>
               </TableColumnItem>
             </TableColumnItems>
           </TableRowEntry>
         </TableRowEntries>
       </TableControl>
     </View>
     <View>
       <Name>process</Name>
       <ViewSelectedBy>
         <TypeName>System.Diagnostics.Process</TypeName>
       </ViewSelectedBy>
       <WideControl>
         <WideEntries>
           <WideEntry>
             <WideItem>
               <PropertyName>ProcessName</PropertyName>
             </WideItem>
           </WideEntry>
         </WideEntries>
       </WideControl>
     </View>
   </ViewDefinitions>
</Configuration>

which makes it much easier to work with

Posted in PowerShell v6 | Leave a comment

where –not

PowerShell v6.1 preview 2 has added the where –not option.

The option adds another parameter to the syntax

where-object <property name> <operator like parameter> <value>

Couple of examples of using the syntax

Get-Process | where CPU -gt 12

Get-Service | where Status -like ‘Stop*’

Use –Not  when you’re looking for properties that aren’t set. For example

Get-Service | where -Not DependentServices

or

Get-Process | where -Not StartTime

Posted in PowerShell v6 | 1 Comment

Calculating standard deviation

Calculating a standard deviation isn’t a difficult exercise but PowerShell v6.1 offers an easier method.

In Windows PowerShell v5.1 and PowerShell v6.0 the Measure-Object cmdlet has this syntax

PS> Get-Command Measure-Object -Syntax

Measure-Object [[-Property] <string[]>] [-InputObject <psobject>] [-Sum] [-Average] [-Maximum] [-Minimum] [<CommonParameters>]

Measure-Object [[-Property] <string[]>] [-InputObject <psobject>] [-Line] [-Word] [-Character] [-IgnoreWhiteSpace] [<CommonParameters>]

In PowerShell v6.1.0-preview.2 this changes to

PS>  Get-Command Measure-Object -Syntax

Measure-Object [[-Property] <string[]>] [-InputObject <psobject>] [-StandardDeviation] [-Sum] [-Average] [-Maximum] [-Minimum] [<CommonParameters>]

Measure-Object [[-Property] <string[]>] [-InputObject <psobject>] [-Line] [-Word] [-Character] [-IgnoreWhiteSpace] [<CommonParameters>]

You’ve now got a standard deviation option.

How do you use it?

PS>  1..517 | Measure-Object -Sum -Average -StandardDeviation

Count             : 517
Average           : 259
Sum               : 133903
Maximum           :
Minimum           :
StandardDeviation : 149.389312424506
Property          :

There’s probably a few other calculations that would be useful to add to Measure-Object

Posted in PowerShell v6 | Leave a comment

PowerShell problem reporting

There seems to be a lot of confusion about PowerShell problem reporting.

The difference between Windows PowerShell (the one you find pre-installed on Windows machines) current version v5.1 and PowerShell (the open source project) current version v6.0 isn’t really understood and that lies at the heart of the problem.

If you have a problem with Windows PowerShell and you think its a bug the place to report it is here – https://windowsserver.uservoice.com/forums/301869-powershell

If you have a problem with PowerShell and you want to report a bug or request a change or new feature the place to do it is here – https://github.com/PowerShell/PowerShell/issues

The two flavours of PowerShell should be regarded as completely different technologies and treated accordingly.

Posted in Powershell | 1 Comment