Behind the PowerShell Pipeline

Behind the PowerShell Pipeline

Archives
Log in
Subscribe
November 3, 2026

Managing WSMan Remoting Sessions

In this issue:

  • Overview
  • Introduction
  • Get-WSManInstance
    • Parsing XML Data
    • Remoting IP Address
    • Enumerating Shells
  • Get-WSManConnectionInfo
  • Summary

Overview

A demonstration of using Get-WSManInstance to get information on open PowerShell remoting sessions using the WSMan protocol. The information is returned as XML so you'll need to perform a few custom conversions to make the data more user-friendly. Finally, I share a function that you can use to summarize the status of a PowerShell remoting session.

Introduction

A few newsletters ago we looked at ways to manage WSMan remoting connections in PowerShell. We wrapped up last time by exploring how to use the WSManInstance cmdlets. I showed you earlier that you can use Get-Process to look for instances of WSManProvHost. This is the process that indicates a remote PowerShell connection. You can glean some information such as the username and when the process started. However, that's not the only way you can discover information about the remote connection.

Get-WSManInstance

Last time, I demonstrated how to use Get-WSManInstance to retrieve WSMan information. Here's a very neat way to look at open sessions on a remote computer.

PS C:\> Get-WSManInstance -ResourceURI Shell -Enumerate -ComputerName SRV1


rsp             : http://schemas.microsoft.com/wbem/wsman/1/windows/shell
lang            : en-US
ShellId         : A0D3ACBB-2A84-429B-866A-22498DC3BF43
Name            : Runspace1
ResourceUri     : http://schemas.microsoft.com/powershell/Microsoft.PowerShell
Owner           : company\artd
ClientIP        : fe80::f36d:fd64:6c68:6b57%5
ProcessId       : 2844
IdleTimeOut     : PT7200.000S
InputStreams    : stdin pr
OutputStreams   : stdout
MaxIdleTimeOut  : PT2147483.647S
Locale          : en-US
DataLocale      : en-US
CompressionMode : XpressCompression
ProfileLoaded   : Yes
Encoding        : UTF8
BufferMode      : Block
State           : Connected
ShellRunTime    : P0DT0H39M42S
ShellInactivity : P0DT0H0M35S
MemoryUsed      : 73MB
ChildProcesses  : 2

I am running this command from a client computer with an account that has admin rights on SRV1. Enumerating the shells shows me open connections.

PS C:\> Invoke-Command { Get-Process -id 2844 } -ComputerName srv1

Handles  NPM(K)    PM(K)      WS(K)     CPU(s)     Id  SI ProcessName           PSComputerName
-------  ------    -----      -----     ------     --  -- -----------           --------------
    525      28    47260      58572       0.23   2844   0 wsmprovhost           srv1

> Remember, Get-WSManInstance doesn't open a WSMan session like Invoke-Command.

Parsing XML Data

The data you see are based on XML values. It might be nice to make some of these values more user-friendly. For example, the detected session is using 73MB of memory. That string value isn't very useful if I'm trying to sort this property on multiple objects. I really need the raw value in bytes so that 73MB is returned as 76546048. I wrote a helper function using regular expressions to do just that.

function _parseMemoryString {
    #convert values like 11MB to 11534336
    [cmdletbinding()]
    param([string]$StringValue)

    switch -Regex ($StringValue ) {
        '\d+KB' {
            $val = 1KB
        }
        '\d+MB' {
            $val = 1MB
        }
        '\d+GB' {
            $val = 1GB
        }
    } #switch
    if ($val) {
        [int]$i = ([regex]'\d+').Match($StringValue).value
        $i * $val
    }
    else {
        Write-Warning "Failed to parse $StringValue"
        $stringValue
    }
} #close function

I'm assuming a remoting session won't be using terabytes of memory, but you could easily modify the function.

PS C:\> _parseMemoryString 73MB
76546048

The other formatting is related to how datetime values are stored in XML. The output includes a value like P0DT0H39M42S. You can translate this once you understand that 0D means 0 days, 0H means 0 hours, 39M means 39 minutes and so on. I could use regular expressions to parse this string and create a TimeSpan object from the values, but there's an even easier way.

The .NET Framework includes a class, [System.Xml.XmlConvert] that is designed for this very problem. We can use the static ToTimeSpan() method to convert the string into a TimeSpan object.

PS C:\> [System.Xml.XmlConvert]::ToTimeSpan('P0DT0H39M42S')

Days              : 0
Hours             : 0
Minutes           : 39
Seconds           : 42
Milliseconds      : 0
Ticks             : 23820000000
TotalDays         : 0.0275694444444444
TotalHours        : 0.661666666666667
TotalMinutes      : 39.7
TotalSeconds      : 2382
TotalMilliseconds : 2382000

This also works for values that you see with IdleTimeout.

PS C:\> [System.Xml.XmlConvert]::ToTimeSpan('PT7200.000S')

Days              : 0
Hours             : 2
Minutes           : 0
Seconds           : 0
Milliseconds      : 0
Ticks             : 72000000000
TotalDays         : 0.0833333333333333
TotalHours        : 2
TotalMinutes      : 120
TotalSeconds      : 7200
TotalMilliseconds : 7200000

If I know how long the shell has been running, I can calculate when the shell started.

(Get-Date).AddSeconds(-([System.Xml.XmlConvert]::ToTimeSpan($_.ShellRunTime).TotalSeconds))

The "trick" is to add a negative number of seconds.

Want to read the full issue?
Already a paid subscriber? Click here to log in.
GitHub
Bluesky
LinkedIn
Mastodon
jdhitsolutions.github.io
Powered by Buttondown, the easiest way to start and grow your newsletter.