Skip to content
Menu
The Lonely Administrator
  • PowerShell Tips & Tricks
  • Books & Training
  • Essential PowerShell Learning Resources
  • Privacy Policy
  • About Me
The Lonely Administrator

Get Remote PowerShell Session Connections

Posted on April 22, 2014

magnifying-glass During a recent PowerShell training class we naturally covered PowerShell remoting. During the discussion I explained that a remote PSSession is essentially transparent to any currently logged on user. Unless of course you reboot the computer! One way you can identify a remote session is by the presence of the wsmprovhost process. You should see this process whenever there is a remote PSSession to the computer. So then the discussion turned to tracking who might have sessions across multiple computers which is especially helpful when dealing with disconnected sessions since you can only see your own sessions. I don't have a perfect solution, but let's see if this helps. Here is Get-PSRemoteSession.

Manage and Report Active Directory, Exchange and Microsoft 365 with
ManageEngine ADManager Plus - Download Free Trial

Exclusive offer on ADManager Plus for US and UK regions. Claim now!
#requires -version 3.0

Function Get-PSRemoteSession {

<#
.SYNOPSIS
Get remote PSSession processes.
.DESCRIPTION
This command uses CIM to retrieve the wsmprovhost process that might be running
on a remote computer. You can use this information to determine how long a 
session has been running and by what user. By default the command shows a 
summary. If you want to see the full detail, use the -Full parameter. The
process owner and runtime will be added to the object in either case.
.PARAMETER Computername
This parameter has aliases of CN, Name and PSComputername
.PARAMETER Full
Write the full process object to the pipeline instead of the summary.
.EXAMPLE
PS C:\> Get-PSRemoteSession lon-dc1

ProcessID      : 7016
CreationDate   : 4/3/2014 1:25:32 PM
Runtime        : 23:36:38.0799372
Owner          : MYDOMAIN\Jeff
PSComputername : lon-dc1

ProcessID      : 4676
CreationDate   : 4/4/2014 12:23:41 PM
Runtime        : 00:38:28.9568735
Owner          : MYDOMAIN\Administrator
PSComputername : lon-dc1

.EXAMPLE
PS C:\> Get-PSRemoteSession lon-dc1 -full | select Owner,ProcessID,VM,WS,runtime

Owner     : MYDOMAIN\Jeff
ProcessID : 7016
VM        : 163262464
WS        : 44392448
Runtime   : 23:47:39.0140240

Owner     : MYDOMAIN\Administrator
ProcessID : 4676
VM        : 180445184
WS        : 46551040
Runtime   : 00:49:29.8899602

Get full process information and select some key properties
.EXAMPLE
PS C:\> get-remotesession chi-dc04,chi-dc01 | Group Owner -NoElement

Count Name                     
----- ----                     
    1 GLOBOMANTICS\jeff        
    2 GLOBOMANTICS\Administr...


Display what user accounts are using remote sessions on the specified computers.

.EXAMPLE
PS C:\> Get-Content c:\work\computers.txt | Get-PSRemoteSession | where {$_.Runtime -gt "16:00:00"}

For a list of computers, get remote PSSessions that have been running longer 
than 16 hours.

.EXAMPLE
PS C:\> get-remotesession chi-dc04,chi-dc01,chi-app01 | sort PSComputername | format-table -GroupBy PSComputername -Property CreationDate,Runtime,Owner


   PSComputerName: chi-app01

CreationDate                 Runtime                     Owner                      
------------                 -------                     -----                      
4/11/2014 9:58:16 AM         00:04:29.8719959            GLOBOMANTICS\Administrator 


   PSComputerName: chi-dc01

CreationDate                 Runtime                     Owner                      
------------                 -------                     -----                      
4/11/2014 9:46:24 AM         00:16:21.2699348            GLOBOMANTICS\Administrator 


   PSComputerName: chi-dc04

CreationDate                 Runtime                     Owner                      
------------                 -------                     -----                      
4/11/2014 9:43:06 AM         00:19:36.8797428            GLOBOMANTICS\jeff          
4/11/2014 9:47:25 AM         00:15:18.0563043            GLOBOMANTICS\Administrator 

.NOTES
Version       : 1.0
Last Updated  : April 11, 2014

Learn more:
 PowerShell in Depth: An Administrator's Guide (http://www.manning.com/jones2/)
 PowerShell Deep Dives (http://manning.com/hicks/)
 Learn PowerShell 3 in a Month of Lunches (http://manning.com/jones3/)
 Learn PowerShell Toolmaking in a Month of Lunches (http://manning.com/jones4/)
 

  ****************************************************************
  * DO NOT USE IN A PRODUCTION ENVIRONMENT UNTIL YOU HAVE TESTED *
  * THOROUGHLY IN A LAB ENVIRONMENT. USE AT YOUR OWN RISK.  IF   *
  * YOU DO NOT UNDERSTAND WHAT THIS SCRIPT DOES OR HOW IT WORKS, *
  * DO NOT USE IT OUTSIDE OF A SECURE, TEST SETTING.             *
  ****************************************************************
.LINK
Get-CimInstance
about_PSSessions
#>

[cmdletbinding()]
Param(
[Parameter(Position=0,
ValueFromPipeline=$True,
ValueFromPipelineByPropertyName=$True)]
[ValidateNotNullorEmpty()]
[Alias("CN","Name","PSComputername")]
[string[]]$Computername,
[switch]$Full
)

Begin {
    Write-Verbose "Starting Get-PSRemoteSession"
} #begin

Process {
foreach ($computer in $computername) {
    #test connection
    Write-Verbose "Testing if computer $computer is pingable"

    #do a single ping to verify computer is up
    If (Test-Connection -ComputerName $computer -count 1 -Quiet) {

        Write-Verbose "Querying $computer"
        Try {
            #use CIM to remotely query the computer
            $data = Get-CimInstance win32_process -filter "name='wsmprovhost.exe'" `
            -ComputerName $computer -ErrorAction Stop -ErrorVariable MyErr

            if ($data) {
                Write-verbose "Found sessions on $computer"
                Write-verbose ($data[0] | out-string)

                #add some custom properties
                $data | Add-Member -membertype ScriptProperty -Name Runtime -value {
                (Get-Date) - $this.creationdate} 
                $data | Add-Member -MemberType ScriptProperty -Name Owner -Value {
                $owner = $this | Invoke-CimMethod -MethodName GetOwner
                #write the owner information
                "$($owner.domain)\$($owner.user)"
                } 
                
                if ($Full) {
                    #write the full process object with additions to the pipeline
                    $data
                }
                else {
                    #get process summary
                    $data | Select ProcessID,CreationDate,RunTime,Owner,PSComputername  
                  }    

            } #if $data

         } #try

         Catch {
           Write-Warning "Could not query $computer"
           Write-Warning $myErr.ErrorRecord.Exception.Message
           Write-Debug "Suspend script to debug `$myErr exception"
         } #catch

     } #if test-connection works
     else {
       Write-Warning "Failed to ping $computer"
     }

} #foreach computer
} #process

End {
 Write-verbose "Ending Get-PSRemoteSession"
} #end

} #end function

This function takes a computername as a parameter. It does a quick ping to verify the computer is running. I probably should have made that optional, but I needed it at the time. The function then queries the computer using Get-CimInstance for all instances of the wsmprovhost.exe process. I'm using CIM because datetime values are automatically formatted which makes it much easier to add a custom property indicating how long the process, and presumably the remote session, have been running. I also add a custom property to get the process Owner. Due to a quirk (bug?) in the CIM cmdlets, I can even query a remote computer running PowerShell 2.0. When using a filter, the CIM cmdlets work with a v2 computer. I won't question it but will take advantage of it.

By default, the function writes a summary object to the pipeline.

get-psremotesession-1

The one thing I have yet to figure out is a way to show what computer each session is connected from. Although even if I could make the correlation with an active network connection, I'm not sure that would help in the event of a disconnected session. Nor can I tell the state of the session from the process.

I included an option to get the full process object so you could run commands like this:

get-psremotesession-2

But I suspect for many of you the summary will suffice. Here are some examples.

Get-Content c:\work\chi.txt | get-psremotesession | out-gridview -title "Remote Sessions"

get-psremotesession-3

get-psremotesession-4

get-psremotesession-5

If you kill the wsmprovhost process, that will break the PSSession so be careful. But at least now you have a way of identifying what sessions might be open. I hope you'll let me know what you think. Enjoy!


Behind the PowerShell Pipeline

Share this:

  • Click to share on X (Opens in new window) X
  • Click to share on Facebook (Opens in new window) Facebook
  • Click to share on Mastodon (Opens in new window) Mastodon
  • Click to share on LinkedIn (Opens in new window) LinkedIn
  • Click to share on Pocket (Opens in new window) Pocket
  • Click to share on Reddit (Opens in new window) Reddit
  • Click to print (Opens in new window) Print
  • Click to email a link to a friend (Opens in new window) Email

Like this:

Like Loading...

Related

6 thoughts on “Get Remote PowerShell Session Connections”

  1. laurelraven says:
    April 22, 2014 at 11:52 am

    Reading through the script, one thing confuses me… $this. I don’t see it set anywhere, so is it a special variable?

    1. Jeffery Hicks says:
      April 22, 2014 at 12:14 pm

      Good eyes. Probably should have mentioned that. I am using Add-Member to define a new property. But instead of a NoteProperty I am creating a ScriptProperty. The value is the result of a scriptblock. In this context you use $this to indicate the current object in the pipeline. I could have taken extra steps to create my own object and type extension, in which case I would have used this same type of code to define the property, but in an XML file. My script does it all on the fly using Add-Member. So yeah, this is a special case.

      1. laurelraven says:
        April 22, 2014 at 2:50 pm

        So, it sounds kind of like $_, but for scriptblocks? I found it searching through about_Automatic_Variables, but the description seems a little vague and hard to wrap my head around.

        Sorry, I know this is a bit off topic for what you were posting; I’d just never seen that one yet.

      2. Jeffery Hicks says:
        April 22, 2014 at 3:23 pm

        That is kinda correct. But as I said this is a special use case. I may have to write an article on this.

  2. Dexter (@DexterPOSH) says:
    April 22, 2014 at 10:21 pm

    When we use the -Filter the CIM Cmdlets it does work with the machine having PowerShell v2…..So does it fall back to using DCOM when the remote machine doesn’t has winrm configured?
    Just wanted to get little insight on this one…..this bug is helpful 🙂

    1. Jeffery Hicks says:
      April 23, 2014 at 6:56 am

      That is the only explanation I can think of.

Comments are closed.

reports

Powered by Buttondown.

Join me on Mastodon

The PowerShell Practice Primer
Learn PowerShell in a Month of Lunches Fourth edition


Get More PowerShell Books

Other Online Content

github



PluralSightAuthor

Active Directory ADSI Automation Backup Books CIM CLI conferences console Friday Fun FridayFun Function functions Get-WMIObject GitHub hashtable HTML Hyper-V Iron Scripter ISE Measure-Object module modules MrRoboto new-object objects Out-Gridview Pipeline PowerShell PowerShell ISE Profile prompt Registry Regular Expressions remoting SAPIEN ScriptBlock Scripting Techmentor Training VBScript WMI WPF Write-Host xml

©2025 The Lonely Administrator | Powered by SuperbThemes!
%d