Recursos / recursos de relatório do Gateway RD

2

Acabamos de implementar o RD Gateway para nosso próprio departamento, em preparação para um esforço para toda a agência de telecomutação. Tudo está configurado e funcionando muito bem, mas eu estava tentando descobrir qual a melhor maneira de monitorar / relatar usuários. Eu vejo software de terceiros por aí que vai fazer isso, mas existe alguma coisa embutida ou via powershell / scripting que eu poderia usar que me daria um relatório da atividade diária dos usuários? Algo a dizer, "Usuário A conectado neste momento, estava ligado por tanto tempo, enviou / recebeu tantos dados"? Basicamente algumas das mesmas coisas que você pode ver no visualizador de eventos. Idealmente, gostaria de ter essa configuração para que, uma vez por dia, ele me enviasse o uso diário para quando um supervisor perguntar se a pessoa está realmente trabalhando (ou pelo menos enviando e recebendo on-line x quantidade de dados), Eu terei algumas métricas para dar a eles. Percebo que a saída real do trabalho é relevante e mais uma questão gerencial, mas gostaria de poder oferecer o máximo que puder do meu lado quando for solicitado.

Pensamentos? Obrigado!

    
por Don 12.04.2012 / 23:57

1 resposta

1

Eu escrevi um script há um tempo atrás, que incluirei no final deste post, mas preciso dizer algumas coisas sobre isso primeiro.

Não é perfeito. Não está funcionando bem o suficiente para usá-lo regularmente. Estou postando porque existem algumas coisas que ajudarão você a decidir implementar sua própria solução com o PowerShell. Isso deve levar você a cerca de 80% do caminho até lá. O motivo para escrever esse script provavelmente teve mais a ver com a experiência com os Gráficos do Google e a consulta de logs de eventos usando filtros XML do que com a descoberta de uma solução viável para relatórios de área de trabalho remota. Eu aparentemente codifiquei algumas coisas lá (como o nome do servidor de terminal) que eu pretendia voltar e consertar (antes de abandoná-lo), como você pode dizer nos meus comentários. O script deve criar um gráfico ou retornar "Nenhuma atividade". Às vezes, simplesmente fica pendurado ...

De qualquer forma, ele criará um gráfico de cores da atividade do usuário em um dia semelhante ao seguinte -

Porfavor,nãouseestescriptcomoexemplodecomoissodeveserfeito,éexatamentecomoeufizhámuitotempoatrás.Semmaisdelongas...

##TODO#1.Maketimingqueriescorrect(withouthard-codingthe+6)param([parameter(Mandatory=$true)][DateTime]#Specifiesdateofinformationtobereturned$QueryDate,[parameter(Mandatory=$true)][String]#Specifiesusertorunreporton$User,[String]#Specifyservertoquery(default:TSSRV)$Server="TSSRV",

    [Switch]
    # Automatically view graph upon completion of command
    $ShowGraph
)

function constructQuery
{
    param
    (
        [DateTime]
        $date = $QueryDate,

        [string]
        $username = $User,

        [Parameter(Mandatory=$false)]
        [string]
        $TargetLogonId,

        [Parameter(Mandatory=$false)]
        [ValidatePattern("[0-3]")]
        [int]
        $queryType, # 0 = EventID4647, 1 = EventID4634, 2 = EventID4779, 3 = EventID4778

        [Parameter(Mandatory=$false)]
        [alias("LastEvent")]
        [int]
        $_lastEvent
    )

    [string]$ReturnQuery = "" #initialize blank query

    [string]$DateFormatString = "{0:yyyy'-'MM'-'dd'T'HH':'mm':'sss'Z'}"
    [string]$StartDateTimeString = $DateFormatString -f $date.AddHours(6) # add 6 stupid hours for timezone...
    [string]$EndDateTimeString = $DateFormatString -f ($date.AddDays(1)).AddHours(6) # add 6 stupid hours for timezone...

    [string]$TimeQueryString = "TimeCreated[@SystemTime>='$StartDateTimeString' and @SystemTime<'$EndDateTimeString']]] and "

    [string]$TargetLogonString = "*[EventData[Data[@Name=''TargetLogonId'']=''$TargetLogonId'']]"
    [string]$LogonIDString = "*[EventData[Data[@Name=''LogonID'']=''$TargetLogonId'']]"

    [string]$QueryHeader = "<QueryList><Query Id='"0'" Path='"Security'">"
    [string]$QueryFooter = "</Query></QueryList>"

    $ReturnQuery += $QueryHeader

    if(!$TargetLogonId) # Query for Logons
    {
        $ReturnQuery += "<Select Path='"Security'">" + '
                            "*[System[(EventID=4624) and " + '
                            $TimeQueryString + '
                            "*[EventData[Data[@Name=''LogonType'']=10]] and " + '
                            "*[EventData[Data[@Name=''TargetUserName'']=''$username'']]" + '
                        "</Select>" + '
                        "<Suppress Path='"Security'">" + '
                            "*[EventData[Data[@Name=''LogonGuid'']=''{00000000-0000-0000-0000-000000000000}'']]" + '
                        "</Suppress>"
    }
    else
    {
        [string]$tempString = "<Select Path='"Security'">" + '
                              "*[System[(EventID={0}) and " + '
                              $TimeQueryString

        switch ($queryType)
        {
            {$_ -eq 0 -or $_ -eq 1} { $tempString += $TargetLogonString }
            {$_ -eq 2 -or $_ -eq 3} { $tempString += $LogonIDString }
            default {Write-Host ERROR; exit}
        }

        $tempString += "{1}" + '
                      "</Select>"

        switch($queryType)
        {
            0 { $ReturnQuery += $tempString -f "4647", "" }
            1 { $ReturnQuery += $tempString -f "4634", "and *[EventData[Data[@Name=''LogonType'']=10]]" }
            2 { $ReturnQuery += $tempString -f "4779", "and *[System[(EventRecordID&gt;$_lastEvent)]]" }
            3 { $ReturnQuery += $tempString -f "4778", "and *[System[(EventRecordID&gt;$_lastEvent)]]" }
            default {Write-Host ERROR; exit}
        }
    }

    $ReturnQuery += $QueryFooter    
    $ReturnQuery
}

function search
{
    param
    (
        [string]
        $_User = $User,

        [Parameter(Mandatory=$false)]
        [string]
        $_TargetLogonId,

        [ref]
        $_lastEvent,

        [ref]
        $_currentEvent,

        [int]
        $_queryType, # Logoff = 1, Disconnect = 2, Reconnect = 3

        [int]
        $_eventIDNumber
    )

    try
    {
        [string]$query = constructQuery -Date $QueryDate -username $User -TargetLogonId $_TargetLogonId -queryType $_queryType -LastEvent $_eventIDNumber
        $query | Out-File -Append c:\TEMP\queries.txt # DEBUG
        $_lastEvent.Value = $_currentEvent.Value # DEBUG
        $_currentEvent.Value = Get-WinEvent -ComputerName $Server -FilterXML $query -Oldest -ErrorAction Stop # DEBUG
        #"SUCCESS" | Out-File -Append c:\TEMP\queries.txt # DEBUG
        $true
    }
    catch
    {
        $false
    }
}

function eventURLBuilder
{
    param
    (
        [System.Diagnostics.Eventing.Reader.EventLogRecord]
        $_currentEvent,

        [System.Diagnostics.Eventing.Reader.EventLogRecord]
        $_lastEvent,

        [alias("Disconnected")]
        [switch]
        $_disconnected
    )

    $lastEventDT = Get-Date $_lastEvent.TimeCreated
    $dTimeStart = [decimal]$lastEventDT.ToString("HH") + [decimal]($lastEventDT.ToString("%m")/60)
    if($_disconnected) { $baseString = "B,$disconnectedColor,0," + ("{0:N2}" -f $dTimeStart) + ":" }
    else { $baseString = "B,$activeColor,0," + ("{0:N2}" -f $dTimeStart) + ":" }
    $currentEventDT = Get-Date $_currentEvent.TimeCreated
    $dTimeFinish = [decimal]$currentEventDT.ToString("HH") + [decimal]($currentEventDT.ToString("%m")/60)

    $baseString + ("{0:N2}" -f $dTimeFinish) + ",0|" # return string
}

## Public Variables ##
[int]$state = 0 # 0=Logged off, 1=Logged on, 2=Disconnected, 3=Reconnected 
[string]$eventsURL = "" # snippet of URL that will hold the data being charted
$totalDisconnectedTime = New-TimeSpan # will contain total disconnected time
$totalLogonTime = New-TimeSpan # will contain total logged on (not disconnected) time
[string]$activeColor = "4D7CFF" #76A4FB
[string]$disconnectedColor = "E86868" #990000
[int]$lastEventProcessed = 0
######################

try
{
    $LogonsQuery = constructQuery
    $LogonEvents = Get-WinEvent -ComputerName $Server -FilterXML $LogonsQuery -Oldest -ErrorAction Stop
}
catch
{
    Write-Host "No activity." -ForegroundColor Red
    exit
}

foreach ($LogonEvent in $LogonEvents)
{
    if($LogonEvent.RecordId -lt $lastEventProcessed)
    {
        continue
    }

    #Extract 'TargetLogonId' from $LogonEvent XML to match related session events
    [xml]$xmlEvent = $LogonEvent.ToXml()
    $xmlns = New-Object -TypeName System.Xml.XmlNamespaceManager -ArgumentList $xmlEvent.NameTable
    $xmlns.AddNamespace("el", "http://schemas.microsoft.com/win/2004/08/events/event")
    [string]$TargetLogonId = $xmlEvent.SelectSingleNode("el:Event/el:EventData/el:Data[@Name = 'TargetLogonId']/text()", $xmlns).Value
    [int]$lastEventProcessed = $LogonEvent.RecordId

    $lastEvent = $LogonEvent    
    $currentEvent = $LogonEvent # initialize (value meaningless at this point)

    $state = 1 # Mark as "logged on"
    while ($state -ne 0)
    {
        if ($state -eq 1) #LOGGED ON
        {
            try
            {
                $hasEvent = search $User $TargetLogonId ([ref]$lastEvent) ([ref]$currentEvent) 2 $lastEventProcessed # 2 = disconnect
            }
            catch
            {
                Write-Host ERROR -ForegroundColor Red
                $_
                exit
            }
            if ($hasEvent)
            {
                try
                {
                    $totalLogonTime += (Get-Date $currentEvent.TimeCreated) - (Get-Date $lastEvent.TimeCreated)
                    $eventsURL += eventURLBuilder $currentEvent $lastEvent
                    $state = 2
                    $lastEventProcessed = $currentEvent.RecordId
                }
                catch
                {
                    Write-Host "ERROR" -ForegroundColor Red
                    $_
                    exit
                }
            }
            if ($state -ne 0 -and $state -ne 2)
            {
                try
                {
                    $hasEvent = search $User $TargetLogonId ([ref]$lastEvent) ([ref]$currentEvent) 1 $lastEventProcessed
                }
                catch
                {
                    Write-Host ERROR -ForegroundColor Red
                    $_
                    exit
                }
                if ($hasEvent)
                {
                    try
                    {
                        $totalLogonTime += (Get-Date $currentEvent.TimeCreated) - (Get-Date $lastEvent.TimeCreated)
                        $eventsURL += eventURLBuilder $currentEvent $lastEvent
                        $state = 0
                    }
                    catch
                    {
                        Write-Host "ERROR" -ForegroundColor Red
                        $_
                        exit
                    }
                }
            }
        }
        elseif ($state -eq 2) #DISCONNECTED
        {
            try
            {
                $hasEvent = search $User $TargetLogonId ([ref]$lastEvent) ([ref]$currentEvent) 3 $lastEventProcessed # 3 = reconnect
            }
            catch
            {
                Write-Host "ERROR" -ForegroundColor Red
                $_
                exit
            }
            if ($hasEvent)
            {
                try
                {
                    $totalDisconnectedTime += (Get-Date $currentEvent.TimeCreated) - (Get-Date $lastEvent.TimeCreated)
                    $eventsURL += eventURLBuilder $currentEvent $lastEvent -Disconnected
                    $state = 3
                    $lastEventProcessed = $currentEvent.RecordId
                }
                catch
                {
                    Write-Host "ERROR" -ForegroundColor Red
                    $_
                    exit
                }
            }
            if ($state -ne 0 -and $state -ne 3)
            {
                try
                {
                    $hasEvent = search $User $TargetLogonId ([ref]$lastEvent) ([ref]$currentEvent) 1 $lastEventProcessed
                }
                catch
                {
                    Write-Host "ERROR" -ForegroundColor Red
                    $_
                    exit
                }
                if ($hasEvent)
                {
                    try
                    {
                        $totalDisconnectedTime += (Get-Date $currentEvent.TimeCreated) - (Get-Date $lastEvent.TimeCreated)
                        $eventsURL += eventURLBuilder $currentEvent $lastEvent -Disconnected
                        $state = 0
                    }
                    catch
                    {
                        Write-Host "ERROR" -ForegroundColor Red
                        $_
                        exit
                    }
                }
            }
        }
        elseif ($state -eq 3) #RECONNECTED
        {
            try
            {
                $hasEvent = search $User $TargetLogonId ([ref]$lastEvent) ([ref]$currentEvent) 2 $lastEventProcessed # 2 = disconnect
            }
            catch
            {
                Write-Host ERROR -ForegroundColor Red
                $_
                exit
            }
            if ($hasEvent)
            {
                try
                {
                    $totalLogonTime += (Get-Date $currentEvent.TimeCreated) - (Get-Date $lastEvent.TimeCreated)
                    $eventsURL += eventURLBuilder $currentEvent $lastEvent
                    $state = 2
                    $lastEventProcessed = $currentEvent.RecordId
                }
                catch
                {
                    Write-Host "ERROR" -ForegroundColor Red
                    $_
                    exit
                }
            }
            if ($state -ne 0 -and $state -ne 2)
            {
                try
                {
                    $hasEvent = search $User $TargetLogonId ([ref]$lastEvent) ([ref]$currentEvent) 1 $lastEventProcessed
                }
                catch
                {
                    Write-Host "ERROR" -ForegroundColor Red
                    $_
                    exit
                }
                if ($hasEvent)
                {
                    try
                    {
                        $totalLogonTime += (Get-Date $currentEvent.TimeCreated) - (Get-Date $lastEvent.TimeCreated)
                        $eventsURL += eventURLBuilder $currentEvent $lastEvent
                        $state = 0
                    }
                    catch
                    {
                        Write-Host "ERROR" -ForegroundColor Red
                        $_
                        exit
                    }
                }
            }
        }
    }
}

$chartURL = "http://chart.googleapis.com/chart?cht=lc&chtt=" + '
            $User + '
            "+Remote+Access+for+" + '
            $QueryDate.ToShortDateString() + '
            "|Total%3A+" + ($totalDisconnectedTime + $totalLogonTime).Hours + "+hours+and+" + ($totalDisconnectedTime + $totalLogonTime).Minutes + "+minutes" + '
            "-- Active%3A+" + $totalLogonTime.Hours + "+hours+and+" + $totalLogonTime.Minutes + "+minutes" + '
            "&chm="
$chartURL += $eventsURL
$chartURL = $chartURL.Remove($chartURL.Length - 1) # remove the extraneous '|' character
$chartURL += "&chxl=0:|12%3A00|3%3A00|6%3A00|9%3A00|12%3A00|3%3A00|6%3A00|9%3A00|12%3A00|1:||AM|PM||2:|&chxtc=0,5&chdl=|Logged+On|Disconnected&chco=FFFFFF|" + '
             $activeColor + '
             "|" + '
             $disconnectedColor + '
             "&chs=800x240&chxt=x,x,y&chd=t:100&chls=FFFFFF&chfd=0,x,0,24,1,100"
$saveFolder = "c:\TEMP\chart.png"
$clnt = new-object System.Net.WebClient
$clnt.DownloadFile($chartUrl,$saveFolder)
if($ShowGraph)
{
    &"$saveFolder"
}
$chartURL | Out-File c:\TEMP\chartURL.txt # DEBUG
Write-Host Chart Generated at $saveFolder -ForegroundColor Green

Para executar este script, faça o seguinte -

.\Get-TSUserReport.ps1 -ShowGraph -QueryDate "4/11/2012" -User jdoe
    
por 13.04.2012 / 15:32