Use PowerShell to Find Logon Sessions

Use PowerShell to Find Logon Sessions

  • Comments 3
  • Likes

Summary: Learn how to use Windows PowerShell to discover logon session information for remote computers.

Microsoft Scripting Guy, Ed Wilson, here. This week we will have one guest blogger for the entire week. Sean Kearney has written a series of blog posts about Windows PowerShell and the Legacy. I am not going to be redundant by reposting his biography each and every day.

Here’s Sean…

Here’s a problem I get daily. I need to access a machine because somebody calls complaining about a problem. Most of the time, I can figure out the problem based on the person’s name and their machine name. But sometimes, well…“Things ain’t just the way ya like ‘em.”

I gave up trying to look at the sessions in computer management. In a larger environment, that’s about as slow as a hamster-powered sports car.

So I went back to the basics and found my old friend NET.EXE—see it on a file server? It already has the answer. Problem is, it contains nothing but IP addresses, and I hate navigating that output.  FIND.EXE is good, but it has limitations too!

So I turned to Windows PowerShell to help me out. Combining Windows PowerShell remoting along with some legacy apps gave me a really cool solution.

First, to see what it looks like, I ran the following script in Windows PowerShell.

(NET SESSION)

This showed me all the open sessions on my file server where most of the users home drives were located. (Your environment may be different, so I recommend picking the machine with a file share that most of the users in your environment are likely to attach to.)

Then to quickly find the user, I piped the output as follows.

SELECT-STRING

(NET SESSION) | Select-String mr.trouble

  

Now to get fancy, I decided to see if I could pass this into the file server via a remote session to allow this to be run from any system.

$S=NEW-PSSESSION –computername MYFILESERVER

INVOKE-COMMAND –Session $s –scriptblock { (NET SESSION) | Select-String mr.trouble }

REMOVE-PSSESSION $S

Now at the very least, I could see a much shorter list and resolve those IP addresses to computer names as follows.

nslookup x.x.x.x

But wait.  Don’t I want all of this as a single function?  Don’t I want to make my life easier? What a concept!

I found a small problem in getting the variable to be received by the remote session, so yes…I cheated. I piped after.  I’ll probably look at this later and find the right answer vs. the “cheaters answer.” 

function global:FIND-HSGUSER {

# Get name of File Server to Initialize Remoting
# and the name of the silly user you need to find their computer for   

param($FILESERVER,$USERNAME)

# Connect Remotely to Server, Run Session, get a list of everybody logged in there

    $S=NEW-PSSESSION –computername $FILESERVER
    $Results=(INVOKE-COMMAND –Session $s –scriptblock { (NET SESSION) }) | Select-string $USERNAME
    REMOVE-PSSESSION $S

# Let’s parse through the data and pull out what we need   

Foreach ( $Part in $RESULTS ) {

    $ComputerIP=$Part.Line.substring(2,21).trim()
    $User=$Part.Line.substring(22,44).trim()

# Use nslookup to identify the computer, grab the line with the “Name:” field in it

    $Computername=(nslookup $ComputerIP | Where { $_ -like 'Name:'})

    If ($Computername -eq $NULL) { $Computername="Unknown"}
    Else { $Computername=$Computername.substring(9).trim()}

    write-host
# Show me where the silly fool is hiding

“$User is logged into $Computername with IP address $ComputerIP”

}

}

Of course this is a far from a perfect solution. I have found that if the IP address isn’t registered in DNS, it pops out an irritating line that bypasses the console output. But it does show a nice way to make life a little easier on the Administrator with Windows PowerShell and the Legacy.

Take it, use it, abuse it, get creative, and see what YOU can do with existing legacy tools. It’s not “taboo,” it’s power to leverage!

“Legacy rules”…and the Power of Shell too.

Guest blogger week will continue tomorrow when Sean will continue to talk about Windows PowerShell and the Legacy. A special thank you to Sean for writing this week’s blog posts. Hope you enjoy them.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • If you have enabled 'Audit account logon Events' on your Win2008 server you can query for event: 4768; A Kerberos Ticket Request.  The event has the username and computername where the request originated from.  Just as your request isn't perfect, neither is this.  Its just an alternative if you dont have a share where all your users are connected to.  

    function Get-UserComputerName {

    <#

    .SYNOPSIS

      Searches a specified Domain Controller for the computername of a logged on user.  

    .DESCRIPTION

      Queries a DC for Event ID 4768 (Kerberos authentication ticket,TGT) request from the servers Security

      event log.

    .PARAMETER UserName

      SamAccount name of the user to search for

    .EXAMPLE

      PS> .\Get-UserComputerName -UserName "John_Doe" -Server "My_DC"

      Searches for user John_Doe on Domain Controller My_DC

    .EXAMPLE

    PS> .\Get-UserComputerName -Username "John_Doe"

    Searches for user John_Doe using the logged on server name for the current user

    running the script.

    .EXAMPLE

    PS> .\Get-UserComputerName

    Searches the current user on the logged on server name

    #>

    param([string]$username = $env:username,[string]$server = $env:logonserver)

    $ErrorActionPreference = "silentlycontinue"

    if ($server.StartsWith("\\")) {$server = $server.Remove(0,2)}

    $events = Get-WinEvent -ComputerName $server -MaxEvents 5 -FilterHashTable @{logname="security";id=4768;data=$username}

    # Check if error has been raised from EventLog Query.

    if (!$?) {Write-Warning "No successful logon events were found on Server: $server for Username: $username"

    break

    }

    foreach ($event in $events) {

    $myObject = New-Object -TypeName system.Object

    [string]$Computer = $event.message.split("`n") | Select-String "Client Address"

    $addressLine = $computer.replace("Client Address:",'')

    $addressLine = $addressLine.trim()

    if ($addressLine.startswith("::ffff:")) { $address = $addressLine.replace("::ffff:",'') }

    $DNSResult = [system.Net.Dns]::Resolve($address)

    $ComputerName = $DNSResult.HostName

    $timeStamp = $event.timecreated

    $myObject | Add-Member -MemberType noteproperty -Name AuthDC -Value $server

    $myObject | Add-Member -MemberType noteproperty -Name TimeStamp -Value $timeStamp

    $myObject | Add-Member -MemberType noteproperty -Name UserName -Value $username

    $myObject | Add-Member -MemberType noteproperty -Name IPAddress -Value $address

    $myObject | Add-Member -MemberType noteproperty -Name ComputerName -Value $computerName

    $myObject

    }

    }

  • Joel

    I like that! Another tool to add to our kits!  I LOVE the Power of community here!  Thanks for contributing.  

    If you have a few minutes, could you pop that into the Script Repository?   NICE JOB! :)

    Sean

  • I also this on my blog at http://datatypes.blogspot.com