Win32_PingStatus can ping one or more computers. This works in a highly unusual way: rather than calling a method, you submit the ping parameters as filter.
Win32_PingStatus is very fast and can ping multiple computers in parallel. When you ping too many systems simultaneously, you may run out of resources, though.
Examples
When you query instances of Win32_PingStatus, no instances are returned. In order to use this class, you need to also specify a filter. The filter submits the information needed to perform a ping: at least a computer name (or IP address), and a timeout:
$ComputerName = 'google.com'
$TimeoutMillisec = 2000
Get-CimInstance -ClassName Win32_PingStatus -Filter "Address='$ComputerName' and timeout=$TimeoutMillisec" | Select-Object -Property Address, StatusCode
A status code of 0 indicates success.
Pinging Multiple Computers
To ping more than one computer, it is better to submit multiple computer names rather than repeating the call because WMI supports parallel operations. This pings three computer names:
# ping the specified servers with a given timeout (milliseconds)
$TimeoutMillisec = 1000
Get-CimInstance -ClassName Win32_PingStatus -Filter "(Address='microsoft.com' or Address='r13-c14' or Address='google.com') and timeout=$TimeoutMillisec" | Select-Object -Property Address, StatusCode
Keep in mind that all ping operations occur simultaneously. When you submit too many computers, you may run out of resources.
When a computer name does not exist, StatusCode returns $null
. Again, a value of 0 indicates success.
Adding Parameters
It is awkward to construct the filter string for multiple computers. PowerShell can do this for you. Simply implement parameters and turn it into a function Test-OnlineFast
:
function Test-OnlineFast
{
param
(
[Parameter(Mandatory)]
[string[]]
$ComputerName,
$TimeoutMillisec = 1000
)
# convert list of computers into a WMI query string
$query = $ComputerName -join "' or Address='"
Get-CimInstance -ClassName Win32_PingStatus -Filter "(Address='$query') and timeout=$TimeoutMillisec" | Select-Object -Property Address, StatusCode
}
Now it is very simple to ping many computers using a timeout of your choice:
Test-OnlineFast -ComputerName microsoft.com, google.de
By default, Test-OnlineFast
uses a timeout of 1000 milliseconds, so when a machine does not respond, it waits a maximum of 1 second. You can change this timeout via -TimeoutMilliseconds.
The more time you grant, the longer the command will take. You should therefore use a timeout that is as small as possible, while still allowing enough time for responding systems to send a response.
Another time factor to consider is DNS resolution: if DNS resolution is slow, or cannot resolve a name, this adds to the overall time it takes. With IP addresses, this slowdown does not occur.
Range Ping
Here is an example that pings 200 IP addresses and takes just a few seconds:
$ComputerName = 1..255 | ForEach-Object { "10.62.13.$_" }
Test-OnlineFast -ComputerName $ComputerName
Friendly Return Values
Win32_PingStatus returns cryptic numeric return values. By adding a hashtable, your function can translate them to meaningful text:
function Test-OnlineFast
{
param
(
# make parameter pipeline-aware
[Parameter(Mandatory)]
[string[]]
$ComputerName,
$TimeoutMillisec = 1000
)
# hash table with error code to text translation
$StatusCode_ReturnValue =
@{
0='Success'
11001='Buffer Too Small'
11002='Destination Net Unreachable'
11003='Destination Host Unreachable'
11004='Destination Protocol Unreachable'
11005='Destination Port Unreachable'
11006='No Resources'
11007='Bad Option'
11008='Hardware Error'
11009='Packet Too Big'
11010='Request Timed Out'
11011='Bad Request'
11012='Bad Route'
11013='TimeToLive Expired Transit'
11014='TimeToLive Expired Reassembly'
11015='Parameter Problem'
11016='Source Quench'
11017='Option Too Big'
11018='Bad Destination'
11032='Negotiating IPSEC'
11050='General Failure'
}
# hash table with calculated property that translates
# numeric return value into friendly text
$statusFriendlyText = @{
# name of column
Name = 'Status'
# code to calculate content of column
Expression = {
# take status code and use it as index into
# the hash table with friendly names
# make sure the key is of same data type (int)
$StatusCode_ReturnValue[([int]$_.StatusCode)]
}
}
# calculated property that returns $true when status -eq 0
$IsOnline = @{
Name = 'Online'
Expression = { $_.StatusCode -eq 0 }
}
# do DNS resolution when system responds to ping
$DNSName = @{
Name = 'DNSName'
Expression = { if ($_.StatusCode -eq 0) {
if ($_.Address -like '*.*.*.*')
{ [Net.DNS]::GetHostByAddress($_.Address).HostName }
else
{ [Net.DNS]::GetHostByName($_.Address).HostName }
}
}
}
# convert list of computers into a WMI query string
$query = $ComputerName -join "' or Address='"
Get-CimInstance -ClassName Win32_PingStatus -Filter "(Address='$query') and timeout=$TimeoutMillisec" |
Select-Object -Property Address, $IsOnline, $DNSName, $statusFriendlyText
}
When you now ping a network segment, you get back fast results and friendly return values:
$iprange = 1..200 | ForEach-Object { "192.168.8.$_" }
Test-OnlineFast -ComputerName $iprange
The result looks similar to this:
Address Online DNSName Status
------- ------ ------- ------
192.168.8.104 True DELL7390.speedport.ip Success
192.168.8.100 True Success
192.168.8.1 True speedport.ip Success
192.168.8.103 True Success
192.168.8.107 True STORAGE2 Success
192.168.8.131 True NPIC69D3F Success
192.168.8.126 True Success
192.168.8.128 True Success
192.168.8.77 True Success
...
Super-Fast Mass-Ping
You can combine all of the above into a powerful mass ping function Test-OnlineFast
: it constructs a filter string that includes all computer names plus the timeout value you want to use, and translates the return values to friendly text:
function Test-OnlineFast
{
param
(
# make parameter pipeline-aware
[Parameter(Mandatory,ValueFromPipeline)]
[string[]]
$ComputerName,
$TimeoutMillisec = 1000
)
begin
{
# use this to collect computer names that were sent via pipeline
[Collections.ArrayList]$bucket = @()
# hash table with error code to text translation
$StatusCode_ReturnValue =
@{
0='Success'
11001='Buffer Too Small'
11002='Destination Net Unreachable'
11003='Destination Host Unreachable'
11004='Destination Protocol Unreachable'
11005='Destination Port Unreachable'
11006='No Resources'
11007='Bad Option'
11008='Hardware Error'
11009='Packet Too Big'
11010='Request Timed Out'
11011='Bad Request'
11012='Bad Route'
11013='TimeToLive Expired Transit'
11014='TimeToLive Expired Reassembly'
11015='Parameter Problem'
11016='Source Quench'
11017='Option Too Big'
11018='Bad Destination'
11032='Negotiating IPSEC'
11050='General Failure'
}
# hash table with calculated property that translates
# numeric return value into friendly text
$statusFriendlyText = @{
# name of column
Name = 'Status'
# code to calculate content of column
Expression = {
# take status code and use it as index into
# the hash table with friendly names
# make sure the key is of same data type (int)
if ($_.StatusCode -eq $null) {
"N/A"
}
else
{
$StatusCode_ReturnValue[([int]$_.StatusCode)]
}
}
}
# calculated property that returns $true when status -eq 0
$IsOnline = @{
Name = 'Online'
Expression = { $_.StatusCode -eq 0 }
}
# do DNS resolution when system responds to ping
$DNSName = @{
Name = 'DNSName'
Expression = { if ($_.StatusCode -eq 0) {
if ($_.Address -like '*.*.*.*')
{ [Net.DNS]::GetHostByAddress($_.Address).HostName }
else
{ [Net.DNS]::GetHostByName($_.Address).HostName }
}
}
}
}
process
{
# add each computer name to the bucket
# we either receive a string array via parameter, or
# the process block runs multiple times when computer
# names are piped
$ComputerName | ForEach-Object {
$null = $bucket.Add($_)
}
}
end
{
# convert list of computers into a WMI query string
$query = $bucket -join "' or Address='"
Get-WmiObject -Class Win32_PingStatus -Filter "(Address='$query') and timeout=$TimeoutMillisec" |
Select-Object -Property Address, $IsOnline, $DNSName, $statusFriendlyText
}
}
This is how you use the function:
Test-OnlineFast -ComputerName google.de, powershellmagazine.com, 10.10.10.200, 127.0.0.1
The result looks similar to this:
Address Online DNSName Status
------- ------ ------- ------
127.0.0.1 True DESKTOP-7AAMJLF Success
google.de True google.de Success
powershellmagazine.com True powershellmagazine.com Success
10.10.10.200 False Request Timed Out
Pipeline Support
In a last step, you might want to add pipeline support for Test-OnlineFast
:
function Test-OnlineFast
{
param
(
# make parameter pipeline-aware
[Parameter(Mandatory,ValueFromPipeline)]
[string[]]
$ComputerName,
$TimeoutMillisec = 1000
)
begin
{
# use this to collect computer names that were sent via pipeline
[Collections.ArrayList]$bucket = @()
# hash table with error code to text translation
$StatusCode_ReturnValue =
@{
0='Success'
11001='Buffer Too Small'
11002='Destination Net Unreachable'
11003='Destination Host Unreachable'
11004='Destination Protocol Unreachable'
11005='Destination Port Unreachable'
11006='No Resources'
11007='Bad Option'
11008='Hardware Error'
11009='Packet Too Big'
11010='Request Timed Out'
11011='Bad Request'
11012='Bad Route'
11013='TimeToLive Expired Transit'
11014='TimeToLive Expired Reassembly'
11015='Parameter Problem'
11016='Source Quench'
11017='Option Too Big'
11018='Bad Destination'
11032='Negotiating IPSEC'
11050='General Failure'
}
# hash table with calculated property that translates
# numeric return value into friendly text
$statusFriendlyText = @{
# name of column
Name = 'Status'
# code to calculate content of column
Expression = {
# take status code and use it as index into
# the hash table with friendly names
# make sure the key is of same data type (int)
if ($_.StatusCode -eq $null) {
"N/A"
}
else
{
$StatusCode_ReturnValue[([int]$_.StatusCode)]
}
}
}
# calculated property that returns $true when status -eq 0
$IsOnline = @{
Name = 'Online'
Expression = { $_.StatusCode -eq 0 }
}
# do DNS resolution when system responds to ping
$DNSName = @{
Name = 'DNSName'
Expression = { if ($_.StatusCode -eq 0) {
if ($_.Address -like '*.*.*.*')
{ [Net.DNS]::GetHostByAddress($_.Address).HostName }
else
{ [Net.DNS]::GetHostByName($_.Address).HostName }
}
}
}
}
process
{
# add each computer name to the bucket
# we either receive a string array via parameter, or
# the process block runs multiple times when computer
# names are piped
$ComputerName | ForEach-Object {
$null = $bucket.Add($_)
}
}
end
{
# convert list of computers into a WMI query string
$query = $bucket -join "' or Address='"
Get-CimInstance -ClassName Win32_PingStatus -Filter "(Address='$query') and timeout=$TimeoutMillisec" |
Select-Object -Property Address, $IsOnline, $DNSName, $statusFriendlyText
}
}
Now you can pipe a list of computer names right into the function:
'microsoft.com','powershell.one','google.com' | Test-OnlineFast -TimeoutMillisec 2000
The result looks similar to this:
Address Online DNSName Status
------- ------ ------- ------
google.com True google.com Success
powershell.one True powershell.one Success
microsoft.com False Request Timed Out
Remote Access
When you use remoting, you can ping other computers from the location of the remote system. To access remote system(s), use the parameter -ComputerName. The example below pings google.com from the perspective of a server named server123.
$ComputerName = 'google.com'
$TimeoutMillisec = 2000
Get-CimInstance -ClassName Win32_PingStatus -Filter "Address='$ComputerName' and timeout=$TimeoutMillisec" | Select-Object -Property Address, StatusCode -ComputerName server123
The example assumes there is a server named server123 that has remoting enabled, and you have the appropriate permissions to access it.
Learn more about accessing remote computers.
Further Reading
Win32_PingStatus comes with parallel optimization built-in but you can also use .NET classes to do pings and control timeouts. Here is a detailed article.
Often, servers and especially clients do not echo ICMP requests for security reasons. That’s why you may want to use a port test instead. Here is an article that provides you with PowerShell code examples to implement your own port scanner.
Methods
Win32_PingStatus has no methods.
Properties
Win32_PingStatus returns 24 properties:
'Address','BufferSize','NoFragmentation','PrimaryAddressResolutionStatus',
'ProtocolAddress','ProtocolAddressResolved','RecordRoute','ReplyInconsistency','ReplySize',
'ResolveAddressNames','ResponseTime','ResponseTimeToLive','RouteRecord','RouteRecordResolved',
'SourceRoute','SourceRouteType','StatusCode','Timeout','TimeStampRecord','TimeStampRecordAddress',
'TimeStampRecordAddressResolved','TimeStampRoute','TimeToLive','TypeofService'
Unless explicitly marked as WRITEABLE, all properties are read-only.
Address
Value of the address requested.
The form of the value can be either the computer name (“wxyz1234”), IPv4 address (“192.168.177.124”), or IPv6 address (“2010:836B:4179::836B:4179”).
BufferSize
Buffer size sent with the ping command. The default value is 32.
NoFragmentation
If $true
, “Do not Fragment” is marked on the packets sent. The default is $false
, not fragmented.
PrimaryAddressResolutionStatus
Status of the address resolution process. If successful, the value is 0 (zero). Any other value indicates an unsuccessful address resolution.
PrimaryAddressResolutionStatus returns a numeric value. To translate it into a meaningful text, use any of the following approaches:
Use Update-Type
Update-Type
tells PowerShell how to interpret the property. This command needs to be executed only once per PowerShell session:
Update-TypeData -MemberName PrimaryAddressResolutionStatus -TypeName "Microsoft.Management.Infrastructure.CimInstance#root/cimv2/win32_pingstatus" -MemberType ScriptProperty -Value {
Enum EnumPrimaryAddressResolutionStatus
{
Success = 0
}
[EnumPrimaryAddressResolutionStatus]($this.PSBase.CimInstanceProperties['PrimaryAddressResolutionStatus'].Value)
} -Force
Get-CimInstance -ClassName Win32_PingStatus -Filter "" | Select-Object -Property Address, BufferSize, NoFragmentation, RecordRoute, ResolveAddressNames, SourceRoute, SourceRouteType, Timeout, TimeStampRoute, TimeToLive, TypeofService, PrimaryAddressResolutionStatus
Use Select-Object
Select-Object
supports calculated properties. When you submit a hashtable, PowerShell dynamically calculates the result:
$PrimaryAddressResolutionStatus = @{
Name = 'PrimaryAddressResolutionStatusText'
Expression = {
$value = $_.PrimaryAddressResolutionStatus
switch([int]$value)
{
0 {'Success'}
default {"$value"}
}
}
}
Get-CimInstance -ClassName Win32_PingStatus -Filter "" | Select-Object -Property Address, PrimaryAddressResolutionStatus, $PrimaryAddressResolutionStatus
Use a PowerShell Hashtable
You can use a PowerShell hashtable to decode numeric values. Use a hashtable like this one:
$PrimaryAddressResolutionStatus_map = @{
0 = 'Success'
}
Use Enum structure
You can cast the raw property values to a new enum type to translate raw numeric values into friendly text. Use an enum like this one:
Enum EnumPrimaryAddressResolutionStatus
{
Success = 0
}
ProtocolAddress
Address that the destination used to reply. The default is “”.
ProtocolAddressResolved
Resolved address corresponding to the ProtocolAddress property. The default is “”.
RecordRoute
How many hops should be recorded while the packet is in route. The default is 0 (zero).
ReplyInconsistency
Inconsistent reply data is reported.
ReplySize
Represents the size of the buffer returned.
ResolveAddressNames
Command resolves address names of output address values. The default is $false
, which indicates no resolution.
ResponseTime
Time elapsed to handle the request.
ResponseTimeToLive
Time to live from the moment the request is received.
RouteRecord
Record of intermediate hops.
RouteRecordResolved
Resolved address that corresponds to the RouteRecord value.
SourceRoute
Comma-separated list of valid Source Routes. The default is “”.
SourceRouteType
Type of source route option to be used on the host list specified in the SourceRoute property. If a value outside of the ValueMap is specified, then 0 (zero) is assumed. The default is 0 (zero).
SourceRouteType returns a numeric value. To translate it into a meaningful text, use any of the following approaches:
Use Update-Type
Update-Type
tells PowerShell how to interpret the property. This command needs to be executed only once per PowerShell session:
Update-TypeData -MemberName SourceRouteType -TypeName "Microsoft.Management.Infrastructure.CimInstance#root/cimv2/win32_pingstatus" -MemberType ScriptProperty -Value {
Enum EnumSourceRouteType
{
None = 0
Loose_Source_Routing = 1
Strict_Source_Routing = 2
}
[EnumSourceRouteType]($this.PSBase.CimInstanceProperties['SourceRouteType'].Value)
} -Force
Get-CimInstance -ClassName Win32_PingStatus -Filter "" | Select-Object -Property Address, BufferSize, NoFragmentation, RecordRoute, ResolveAddressNames, SourceRoute, SourceRouteType, Timeout, TimeStampRoute, TimeToLive, TypeofService, SourceRouteType
Use Select-Object
Select-Object
supports calculated properties. When you submit a hashtable, PowerShell dynamically calculates the result:
$SourceRouteType = @{
Name = 'SourceRouteTypeText'
Expression = {
$value = $_.SourceRouteType
switch([int]$value)
{
0 {'None'}
1 {'Loose Source Routing'}
2 {'Strict Source Routing'}
default {"$value"}
}
}
}
Get-CimInstance -ClassName Win32_PingStatus -Filter "" | Select-Object -Property Address, SourceRouteType, $SourceRouteType
Use a PowerShell Hashtable
You can use a PowerShell hashtable to decode numeric values. Use a hashtable like this one:
$SourceRouteType_map = @{
0 = 'None'
1 = 'Loose Source Routing'
2 = 'Strict Source Routing'
}
Use Enum structure
You can cast the raw property values to a new enum type to translate raw numeric values into friendly text. Use an enum like this one:
Enum EnumSourceRouteType
{
None = 0
Loose_Source_Routing = 1
Strict_Source_Routing = 2
}
StatusCode
Ping command status codes.
StatusCode returns a numeric value. To translate it into a meaningful text, use any of the following approaches:
Use Update-Type
Update-Type
tells PowerShell how to interpret the property. This command needs to be executed only once per PowerShell session:
Update-TypeData -MemberName StatusCode -TypeName "Microsoft.Management.Infrastructure.CimInstance#root/cimv2/win32_pingstatus" -MemberType ScriptProperty -Value {
Enum EnumStatusCode
{
Success = 0
Buffer_Too_Small = 11001
Destination_Net_Unreachable = 11002
Destination_Host_Unreachable = 11003
Destination_Protocol_Unreachable = 11004
Destination_Port_Unreachable = 11005
No_Resources = 11006
Bad_Option = 11007
Hardware_Error = 11008
Packet_Too_Big = 11009
Request_Timed_Out = 11010
Bad_Request = 11011
Bad_Route = 11012
TimeToLive_Expired_Transit = 11013
TimeToLive_Expired_Reassembly = 11014
Parameter_Problem = 11015
Source_Quench = 11016
Option_Too_Big = 11017
Bad_Destination = 11018
Negotiating_IPSEC = 11032
General_Failure = 11050
}
[EnumStatusCode]($this.PSBase.CimInstanceProperties['StatusCode'].Value)
} -Force
Get-CimInstance -ClassName Win32_PingStatus -Filter "" | Select-Object -Property Address, BufferSize, NoFragmentation, RecordRoute, ResolveAddressNames, SourceRoute, SourceRouteType, Timeout, TimeStampRoute, TimeToLive, TypeofService, StatusCode
Use Select-Object
Select-Object
supports calculated properties. When you submit a hashtable, PowerShell dynamically calculates the result:
$StatusCode = @{
Name = 'StatusCodeText'
Expression = {
$value = $_.StatusCode
switch([int]$value)
{
0 {'Success'}
11001 {'Buffer Too Small'}
11002 {'Destination Net Unreachable'}
11003 {'Destination Host Unreachable'}
11004 {'Destination Protocol Unreachable'}
11005 {'Destination Port Unreachable'}
11006 {'No Resources'}
11007 {'Bad Option'}
11008 {'Hardware Error'}
11009 {'Packet Too Big'}
11010 {'Request Timed Out'}
11011 {'Bad Request'}
11012 {'Bad Route'}
11013 {'TimeToLive Expired Transit'}
11014 {'TimeToLive Expired Reassembly'}
11015 {'Parameter Problem'}
11016 {'Source Quench'}
11017 {'Option Too Big'}
11018 {'Bad Destination'}
11032 {'Negotiating IPSEC'}
11050 {'General Failure'}
default {"$value"}
}
}
}
Get-CimInstance -ClassName Win32_PingStatus -Filter "" | Select-Object -Property Address, StatusCode, $StatusCode
Use a PowerShell Hashtable
You can use a PowerShell hashtable to decode numeric values. Use a hashtable like this one:
$StatusCode_map = @{
0 = 'Success'
11001 = 'Buffer Too Small'
11002 = 'Destination Net Unreachable'
11003 = 'Destination Host Unreachable'
11004 = 'Destination Protocol Unreachable'
11005 = 'Destination Port Unreachable'
11006 = 'No Resources'
11007 = 'Bad Option'
11008 = 'Hardware Error'
11009 = 'Packet Too Big'
11010 = 'Request Timed Out'
11011 = 'Bad Request'
11012 = 'Bad Route'
11013 = 'TimeToLive Expired Transit'
11014 = 'TimeToLive Expired Reassembly'
11015 = 'Parameter Problem'
11016 = 'Source Quench'
11017 = 'Option Too Big'
11018 = 'Bad Destination'
11032 = 'Negotiating IPSEC'
11050 = 'General Failure'
}
Use Enum structure
You can cast the raw property values to a new enum type to translate raw numeric values into friendly text. Use an enum like this one:
Enum EnumStatusCode
{
Success = 0
Buffer_Too_Small = 11001
Destination_Net_Unreachable = 11002
Destination_Host_Unreachable = 11003
Destination_Protocol_Unreachable = 11004
Destination_Port_Unreachable = 11005
No_Resources = 11006
Bad_Option = 11007
Hardware_Error = 11008
Packet_Too_Big = 11009
Request_Timed_Out = 11010
Bad_Request = 11011
Bad_Route = 11012
TimeToLive_Expired_Transit = 11013
TimeToLive_Expired_Reassembly = 11014
Parameter_Problem = 11015
Source_Quench = 11016
Option_Too_Big = 11017
Bad_Destination = 11018
Negotiating_IPSEC = 11032
General_Failure = 11050
}
Timeout
Time-out value in milliseconds.
If a response is not received in this time, no response is assumed. The default is 1000 milliseconds.
TimeStampRecord
Record of time stamps for intermediate hops.
TimeStampRecordAddress
Intermediate hop that corresponds to the TimeStampRecord value.
TimeStampRecordAddressResolved
Resolved address that corresponds to the TimeStampRecordAddress value.
TimeStampRoute
How many hops should be recorded with time stamp information while the packet is in route.
A time stamp is the number of milliseconds that have passed since midnight Universal Time (UT).
If the time is not available in milliseconds or cannot be provided with respect to midnight UT, then any time may be inserted as a time stamp, provided the high order bit of the Timestamp property is set to 1 (one) to indicate the use of a nonstandard value. The default is 0 (zero).
TimeToLive
Life span of the ping packet in seconds.
The value is treated as an upper limit. All routers must decrement this value by 1 (one). When this value becomes 0 (zero), the packet is dropped by the router.
The default value is 80 seconds. The hops between routers rarely take this amount of time.
TypeofService
Type of service that is used. The default value is 0 (zero).
TypeofService returns a numeric value. To translate it into a meaningful text, use any of the following approaches:
Use Update-Type
Update-Type
tells PowerShell how to interpret the property. This command needs to be executed only once per PowerShell session:
Update-TypeData -MemberName TypeofService -TypeName "Microsoft.Management.Infrastructure.CimInstance#root/cimv2/win32_pingstatus" -MemberType ScriptProperty -Value {
Enum EnumTypeofService
{
Normal = 0
Minimize_Cost = 2
Maximize_Reliability = 4
Maximize_Throughput = 8
Minimize_Delay = 16
}
[EnumTypeofService]($this.PSBase.CimInstanceProperties['TypeofService'].Value)
} -Force
Get-CimInstance -ClassName Win32_PingStatus -Filter "" | Select-Object -Property Address, BufferSize, NoFragmentation, RecordRoute, ResolveAddressNames, SourceRoute, SourceRouteType, Timeout, TimeStampRoute, TimeToLive, TypeofService, TypeofService
Use Select-Object
Select-Object
supports calculated properties. When you submit a hashtable, PowerShell dynamically calculates the result:
$TypeofService = @{
Name = 'TypeofServiceText'
Expression = {
$value = $_.TypeofService
switch([int]$value)
{
0 {'Normal'}
2 {'Minimize Cost'}
4 {'Maximize Reliability'}
8 {'Maximize Throughput'}
16 {'Minimize Delay'}
default {"$value"}
}
}
}
Get-CimInstance -ClassName Win32_PingStatus -Filter "" | Select-Object -Property Address, TypeofService, $TypeofService
Use a PowerShell Hashtable
You can use a PowerShell hashtable to decode numeric values. Use a hashtable like this one:
$TypeofService_map = @{
0 = 'Normal'
2 = 'Minimize Cost'
4 = 'Maximize Reliability'
8 = 'Maximize Throughput'
16 = 'Minimize Delay'
}
Use Enum structure
You can cast the raw property values to a new enum type to translate raw numeric values into friendly text. Use an enum like this one:
Enum EnumTypeofService
{
Normal = 0
Minimize_Cost = 2
Maximize_Reliability = 4
Maximize_Throughput = 8
Minimize_Delay = 16
}
CDXML Definition
You can turn this WMI class and its methods into PowerShell cmdlets by importing below CDXML file (Cmdlet Definition XML) as a module.
Create Win32_PingStatus.cdxml
$folder = "c:\wmi\Win32_PingStatus"
$cdxmlPath = Join-Path -Path $folder -ChildPath "Win32_PingStatus.cdxml"
# create folder if not present:
$exists = Test-Path -Path $folder
if (!$exists) { $null = New-Item -Path $folder -ItemType Directory }
# write file
$content = @'
<?xml version="1.0" encoding="utf-8"?>
<!--
This file is licensed under 'Attribution 4.0 International' license (https://creativecommons.org/licenses/by/4.0/).
You can free of charge use this code in commercial and non-commercial code, and you can freely modify and adjust the code
as long as you give appropriate credit to the original author Dr. Tobias Weltner.
This material was published and is maintained here:
https://powershell.one/wmi/root/cimv2/win32_pingstatus#cdxml-definition
-->
<PowerShellMetadata xmlns="http://schemas.microsoft.com/cmdlets-over-objects/2009/11">
<!--referencing the WMI class this cdxml uses-->
<Class ClassName="Root/CIMV2\Win32_PingStatus" ClassVersion="2.0">
<Version>1.0</Version>
<!--default noun used by Get-cmdlets and when no other noun is specified. By convention, we use the prefix "WMI" and the base name of the WMI class involved. This way, you can easily identify the underlying WMI class.-->
<DefaultNoun>WmiPingStatus</DefaultNoun>
<!--define the cmdlets that work with class instances.-->
<InstanceCmdlets>
<!--query parameters to select instances. This is typically empty for classes that provide only one instance-->
<GetCmdletParameters />
<!--defining additional cmdlets that modifies instance properties-->
</InstanceCmdlets>
</Class>
<!--defining enumerations-->
<Enums>
<Enum EnumName="Win32_PingStatus.PrimaryAddressResolutionStatus" UnderlyingType="system.uint32">
<Value Name="Success" Value="0" />
</Enum>
<Enum EnumName="Win32_PingStatus.SourceRouteType" UnderlyingType="system.uint32">
<Value Name="None" Value="0" />
<Value Name="Loose_Source_Routing" Value="1" />
<Value Name="Strict_Source_Routing" Value="2" />
</Enum>
<Enum EnumName="Win32_PingStatus.StatusCode" UnderlyingType="system.uint32">
<Value Name="Success" Value="0" />
<Value Name="Buffer_Too_Small" Value="11001" />
<Value Name="Destination_Net_Unreachable" Value="11002" />
<Value Name="Destination_Host_Unreachable" Value="11003" />
<Value Name="Destination_Protocol_Unreachable" Value="11004" />
<Value Name="Destination_Port_Unreachable" Value="11005" />
<Value Name="No_Resources" Value="11006" />
<Value Name="Bad_Option" Value="11007" />
<Value Name="Hardware_Error" Value="11008" />
<Value Name="Packet_Too_Big" Value="11009" />
<Value Name="Request_Timed_Out" Value="11010" />
<Value Name="Bad_Request" Value="11011" />
<Value Name="Bad_Route" Value="11012" />
<Value Name="TimeToLive_Expired_Transit" Value="11013" />
<Value Name="TimeToLive_Expired_Reassembly" Value="11014" />
<Value Name="Parameter_Problem" Value="11015" />
<Value Name="Source_Quench" Value="11016" />
<Value Name="Option_Too_Big" Value="11017" />
<Value Name="Bad_Destination" Value="11018" />
<Value Name="Negotiating_IPSEC" Value="11032" />
<Value Name="General_Failure" Value="11050" />
</Enum>
<Enum EnumName="Win32_PingStatus.TypeofService" UnderlyingType="system.uint32">
<Value Name="Normal" Value="0" />
<Value Name="Minimize_Cost" Value="2" />
<Value Name="Maximize_Reliability" Value="4" />
<Value Name="Maximize_Throughput" Value="8" />
<Value Name="Minimize_Delay" Value="16" />
</Enum>
</Enums>
</PowerShellMetadata>
'@ | Set-Content -LiteralPath $cdxmlPath -Encoding UTF8
# import module
Import-Module -Name $cdxmlPath -Force -Verbose
# list new cmdlets
Get-Command -Module "Win32_PingStatus"
See here for more information on CDXML and CDXML-based PowerShell modules.
Type Extensions for PowerShell
You can automatically improve properties of class instances by using a types.ps1xml file.
Create Win32_PingStatus.Types.ps1xml
$folder = "c:\wmi\Win32_PingStatus"
$typesPath = Join-Path -Path $folder -ChildPath "Win32_PingStatus.Types.ps1xml"
# create folder if not present:
$exists = Test-Path -Path $folder
if (!$exists) { $null = New-Item -Path $folder -ItemType Directory }
# write file
$content = @'
<?xml version="1.0" encoding="utf-8"?>
<!--
This file is licensed under 'Attribution 4.0 International' license (https://creativecommons.org/licenses/by/4.0/).
You can free of charge use this code in commercial and non-commercial code, and you can freely modify and adjust the code
as long as you give appropriate credit to the original author Dr. Tobias Weltner.
This material was published and is maintained here:
https://powershell.one/wmi/root/cimv2/win32_pingstatus#typesps1xml-file
-->
<Types>
<Type>
<!--@
Applicable type. This type is produced by Get-CimInstance.
To extend instances produced by Get-WmiObject, change the type name to:
System.Management.ManagementObject#root/cimv2\Win32_PingStatus
@-->
<Name>Microsoft.Management.Infrastructure.CimInstance#Root/CIMV2/Win32_PingStatus</Name>
<Members>
<ScriptProperty>
<Name>PrimaryAddressResolutionStatus</Name>
<!--casting raw content to a enum. This translates numeric values to friendly text while leaving the original property value untouched:-->
<GetScriptBlock>[Microsoft.PowerShell.Cmdletization.GeneratedTypes.Win32_PingStatus.PrimaryAddressResolutionStatus]($this.PSBase.CimInstanceProperties['PrimaryAddressResolutionStatus'].Value)</GetScriptBlock>
</ScriptProperty>
<ScriptProperty>
<Name>SourceRouteType</Name>
<!--casting raw content to a enum. This translates numeric values to friendly text while leaving the original property value untouched:-->
<GetScriptBlock>[Microsoft.PowerShell.Cmdletization.GeneratedTypes.Win32_PingStatus.SourceRouteType]($this.PSBase.CimInstanceProperties['SourceRouteType'].Value)</GetScriptBlock>
</ScriptProperty>
<ScriptProperty>
<Name>StatusCode</Name>
<!--casting raw content to a enum. This translates numeric values to friendly text while leaving the original property value untouched:-->
<GetScriptBlock>[Microsoft.PowerShell.Cmdletization.GeneratedTypes.Win32_PingStatus.StatusCode]($this.PSBase.CimInstanceProperties['StatusCode'].Value)</GetScriptBlock>
</ScriptProperty>
<ScriptProperty>
<Name>TypeofService</Name>
<!--casting raw content to a enum. This translates numeric values to friendly text while leaving the original property value untouched:-->
<GetScriptBlock>[Microsoft.PowerShell.Cmdletization.GeneratedTypes.Win32_PingStatus.TypeofService]($this.PSBase.CimInstanceProperties['TypeofService'].Value)</GetScriptBlock>
</ScriptProperty>
</Members>
</Type>
</Types>
'@ | Set-Content -LiteralPath $typesPath -Encoding UTF8
# import type definition
Update-TypeData -PrependPath $typesPath
Note: Win32_PingStatus.Types.ps1xml is using enumerations defined in ClassName.cdxml which are available only when you imported the .cdxml file via
Import-Module
.
Or, you can manually update the PowerShell type database using Update-TypeData
.
View Update-TypeData
commands for Win32_PingStatus properties
Update-TypeData -MemberName PrimaryAddressResolutionStatus -TypeName "Microsoft.Management.Infrastructure.CimInstance#root/cimv2/win32_pingstatus" -MemberType ScriptProperty -Value {
Enum EnumPrimaryAddressResolutionStatus
{
Success = 0
}
[EnumPrimaryAddressResolutionStatus]($this.PSBase.CimInstanceProperties['PrimaryAddressResolutionStatus'].Value)
} -Force
Update-TypeData -MemberName SourceRouteType -TypeName "Microsoft.Management.Infrastructure.CimInstance#root/cimv2/win32_pingstatus" -MemberType ScriptProperty -Value {
Enum EnumSourceRouteType
{
None = 0
Loose_Source_Routing = 1
Strict_Source_Routing = 2
}
[EnumSourceRouteType]($this.PSBase.CimInstanceProperties['SourceRouteType'].Value)
} -Force
Update-TypeData -MemberName StatusCode -TypeName "Microsoft.Management.Infrastructure.CimInstance#root/cimv2/win32_pingstatus" -MemberType ScriptProperty -Value {
Enum EnumStatusCode
{
Success = 0
Buffer_Too_Small = 11001
Destination_Net_Unreachable = 11002
Destination_Host_Unreachable = 11003
Destination_Protocol_Unreachable = 11004
Destination_Port_Unreachable = 11005
No_Resources = 11006
Bad_Option = 11007
Hardware_Error = 11008
Packet_Too_Big = 11009
Request_Timed_Out = 11010
Bad_Request = 11011
Bad_Route = 11012
TimeToLive_Expired_Transit = 11013
TimeToLive_Expired_Reassembly = 11014
Parameter_Problem = 11015
Source_Quench = 11016
Option_Too_Big = 11017
Bad_Destination = 11018
Negotiating_IPSEC = 11032
General_Failure = 11050
}
[EnumStatusCode]($this.PSBase.CimInstanceProperties['StatusCode'].Value)
} -Force
Update-TypeData -MemberName TypeofService -TypeName "Microsoft.Management.Infrastructure.CimInstance#root/cimv2/win32_pingstatus" -MemberType ScriptProperty -Value {
Enum EnumTypeofService
{
Normal = 0
Minimize_Cost = 2
Maximize_Reliability = 4
Maximize_Throughput = 8
Minimize_Delay = 16
}
[EnumTypeofService]($this.PSBase.CimInstanceProperties['TypeofService'].Value)
} -Force
Requirements
To use Win32_PingStatus, the following requirements apply:
PowerShell
Get-CimInstance
was introduced with PowerShell Version 3.0, which in turn was introduced on clients with Windows 8 and on servers with Windows Server 2012.
If necessary, update Windows PowerShell to Windows PowerShell 5.1, or install PowerShell 7 side-by-side.
Operating System
Win32_PingStatus was introduced on clients with Windows Vista and on servers with Windows Server 2008.
Namespace
Win32_PingStatus lives in the namespace root/cimv2. This is the default namespace. There is no need to use the -Namespace parameter in Get-CimInstance
.
Implementation
Win32_PingStatus is implemented in Wmipicmp.dll and defined in Wmipicmp.mof. Both files are located in the folder C:\Windows\system32\wbem
:
explorer $env:windir\system32\wbem
notepad $env:windir\system32\wbem\Wmipicmp.mof