문제

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?

도움이 되었습니까?

해결책

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

다른 팁

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

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)

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
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top