How to find amount of time mstsc is used and by whom?
Asked Answered
T

4

3

Our team has geographically dispersed and many virtual machine will be connected by them using remote desktop. I would like to find who is accessing a remote desktop session and how long it is being used.

I tried to do it with powershell. I wrote a script where user will invoke mstsc using powershell. It will log who has logged in and when he logged. But i would like to find when some one log off from mstsc or disconnect mstsc . Is there any way to capture that information in log file using powershell. Whether any event will be triggered while closing mstsc which could be used for it?

Ternion answered 23/12, 2011 at 6:19 Comment(0)
P
5

I wrote a PowerShell module,PSTerminalServices (http://psterminalservices.codeplex.com), that is built on Cassia. Here's a sample command output:

PS> Get-TSSession | fl *

IPAddress          :
State              : Active
ApplicationName    :
Local              : False
RemoteEndPoint     :
InitialProgram     :
WorkingDirectory   :
ClientProtocolType : Console
ClientProductId    : 0
ClientHardwareId   : 0
ClientDirectory    :
ClientDisplay      : Cassia.Impl.ClientDisplay
ClientBuildNumber  : 0
Server             : Cassia.Impl.TerminalServer
ClientIPAddress    :
WindowStationName  : Console
DomainName         : homelab
UserAccount        : homelab\shay
ClientName         :
ConnectionState    : Active
ConnectTime        : 12/15/2011 2:47:02 PM
CurrentTime        : 12/23/2011 4:35:21 PM
DisconnectTime     :
LastInputTime      :
LoginTime          : 12/15/2011 3:11:58 PM
IdleTime           : 00:00:00
SessionId          : 1
UserName           : shay
Personal answered 23/12, 2011 at 14:41 Comment(8)
I use this module on a frequent basis (for basically the same reason as the OP needs it, to figure out the usage pattern of my VMs) and I can highly recommend it.Virgil
@Shay Levy: I am getting this error. Exception calling "Open" with "0" argument(s): "The RPC server is unavailable" .Port 445 is opened but still getting.Ternion
@Winfred: May i know how do you use it? I mean , will you execute with list of ip address every day evening and find whether the machines were used today? or how do you determine the usage pattern? IF you wish i could ask it as a separate question.Ternion
Is there a firewall in between?Personal
Can you verify that there is a service listening on port 445 on the target?Personal
@Samselvaprabu: added it as a separate answer, with code example.Virgil
@Shay Levy: There is a firewall in between. But the port 445 is listening. I have verified it. Is there any other reason? [ Or can you add in your module a condition to verify that the port 445 listens]. I have verified using following command "(new-object Net.Sockets.TcpClient).Connect($host, $port)". It says that the port 445 listensTernion
Can you please add that tot he Discussions area of the project (psterminalservices.codeplex.com/discussions)? Thanks.Personal
D
4

You could use Cassia to get rdp session information (which could be periodically logged to a log file).

Here's a quick example of how to use cassia in Powershell:

[reflection.assembly]::loadfile("d:\cassia.dll")
$manager = new-object Cassia.TerminalServicesManager
$server = $manager.GetRemoteServer("<name of your server>")
$server.open()
$server.getsessions()

It will return something like this (for every session):

ClientDisplay     : Cassia.Impl.ClientDisplay
ClientBuildNumber : 0
Server            : Cassia.Impl.TerminalServer
ClientIPAddress   : 
WindowStationName : 
DomainName        : CONTOSO
UserAccount       : CONTOSO\admin
ClientName        : 
ConnectionState   : Disconnected
ConnectTime       : 22/12/2011 19:02:00
CurrentTime       : 23/12/2011 9:00:42
DisconnectTime    : 22/12/2011 22:22:35
LastInputTime     : 22/12/2011 22:22:35
LoginTime         : 22/12/2011 10:40:21
IdleTime          : 10:38:06.4220944
SessionId         : 33
UserName          : admin
Disenthrall answered 23/12, 2011 at 8:12 Comment(5)
I tried execute that and got following error. I searched that link also but no useful info. Exception calling "Open" with "0" argument(s): "The RPC server is unavailable" At D:\My_Scripts\Mstsc-monitor.ps1:4 char:13 + $server.Open <<<< () + CategoryInfo : NotSpecified: (:) [], MethodInvocationException + FullyQualifiedErrorId : DotNetMethodExceptionTernion
Did you replace <name of your server> with the hostname of your server?Disenthrall
I used IP address in the place Name of your server.Ternion
Check if you can telnet your server on port 445. Telnet <serverip> 445Disenthrall
Thanks for your tip. That port was closed. I verified it with another machine which has that port opened. It works fineTernion
S
1

If you can establish an RPC connexion with the server itself you can use QWinsta.exe to see who is logon a TS and RWinsta.exe to remote close a connexion (see Managing Terminal Services Sessions Remotely)

Shorthand answered 23/12, 2011 at 8:47 Comment(0)
V
1

I run this function once per 15 minutes, it relies on Module PSTerminalServices. Basically what it does, is it pulls the last time someone RDPed in, then stores it in an XML, overwritting an older value if it exists, if no one is currently logged on, it returns the latest value from the XML instead.

Function Get-LastLogonTime
{
<#

.SYNOPSIS

Get-LastLogonTime returns the last date that someone logged on to a computer.

.DESCRIPTION

Get-LastLogonTime returns the last date that someone logged to a computer.
If admin rights are missing on the server it will return False.

.EXAMPLE

Get-LastLogonTime "nameofcomputer"

.NOTES

gets last access time from the user folder

.LINK

http://winfred.com
#>
Param(
[Parameter(Position=0, Mandatory=$true)]$ComputerName
)
    $StoredRDPSessions = Import-Clixml "RDPSessions.xml"

    $myobj = "" | select ComputerName, LastAccessedDate, UserName
    $myobj.ComputerName = $ComputerName
    $LastConnectedUser = Get-TSSession -ComputerName $ComputerName | where `
    {
        ($_.WindowStationName -ne "Services") -and `
        ($_.State -ne "Listening") -and `
        ($_.WindowStationName -ne "Console")
    } | sort-object -property LastAccessTime -Descending
    if($LastConnectedUser -is [array])
    {
        $myobj.LastAccessedDate = $LastConnectedUser[0].ConnectTime
        $myobj.UserName = $LastConnectedUser[0].UserName
    }elseif($LastConnectedUser){
        $myobj.LastAccessedDate = $LastConnectedUser.ConnectTime
        $myobj.UserName = $LastConnectedUser.UserName
    }else{
        $myobj.LastAccessedDate = $Null
        $myobj.UserName = "Unknown"
    }
    if(($myobj.LastAccessedDate) -and ($myobj.UserName))
    {
        $StoredRDPSession = $StoredRDPSessions | where {$_.ComputerName -eq $ComputerName}
        if($StoredRDPSession)
        {
            if($myobj.LastAccessedDate -gt $StoredRDPSession.LastAccessedDate)
            {
                write-verbose "Newer LastAccessedDate, updating XML"
                $StoredRDPSession.LastAccessedDate = $myobj.LastAccessedDate
                $StoredRDPSession.UserName = $myobj.UserName
                $StoredRDPSessions | Export-Clixml "RDPSessions.xml"
            }
        }else{
            write-verbose "No Entry found Adding to XML"
            $NewStoredRDPSessions = @()
            $StoredRDPSessions | % {$NewStoredRDPSessions += $_}
            $NewStoredRDPSessions += $myobj
            $NewStoredRDPSessions | Export-Clixml "RDPSessions.xml"
        }
    }

    if((!($myobj.LastAccessedDate)) -and $StoredRDPSessions)
    {
        write-verbose "no current session, pulling from stored XML"
        $StoredRDPSession = $StoredRDPSessions | where {$_.ComputerName -eq $ComputerName}
        if($StoredRDPSession)
        {
            $myobj.LastAccessedDate = $StoredRDPSession.LastAccessedDate
            $myobj.UserName = $StoredRDPSession.UserName
        }else{
            write-verbose "Sadness, nothing stored in XML either."
        }
    }
    write-verbose "Get-LastLogonTime $ComputerName - $($myobj.LastAccessedDate) - $($myobj.UserName)"
    Return $myobj
}
Virgil answered 24/1, 2012 at 21:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.