我们刚刚为自己的部门实施了RD网关,准备推动整个远程办公机构。 这一切都设置和工作很好,但我想弄清楚如何最好的监测/报告的用户。 我看到有第三方软件可以做,但是有什么内置的或通过PowerShell /脚本,我可以使用它会给我一个用户的日常活动的报告? 有话要说,“这时用户A连接了这么久,发送/接收了这么多的数据”? 基本上可以在事件查看器中看到的一些相同的东西。 理想情况下,我希望能够进行这种设置,以便每天一次向主pipe发送电子邮件,告知主pipe是否正在实际工作(或至less在线发送和接收x数据量)的日常用法,我会有一些指标给他们。 我意识到,实际的工作成果是相关的,更多是一个pipe理问题,但是我希望在被问到时能够从我的最后提供尽可能多的东西。
思考? 谢谢!
我后面写了一个脚本,我将在这篇文章的底部介绍,但是我需要先说一些。
这并不完美。 它甚至不够好,我经常使用它。 我正在发布它,因为如果您决定使用PowerShell来推出自己的解决scheme,那么有些东西可以帮助您。 这应该会让你有大约80%的路程。 编写这个脚本的原因可能更多的在于使用XMLfilter试验Google Charts和查询事件日志,而不是实际上为远程桌面报告find可行的解决scheme。 我明显硬编码了一些东西(比如terminal服务器的名字),我想回过头去修复(在我放弃它之前),正如你从我的评论中可以看出的那样。 该脚本应该创build一个graphics或返回“无活动”。 有时只是彻头彻尾的挂起
无论如何,它会在一天内创build用户活动的颜色图表,如下所示 –

请不要使用这个脚本作为例子,应该怎么做,这只是我很久以前做的。 无需再费周折…
## TO DO # 1. Make timing queries correct (without hard-coding the +6) param ( [parameter(Mandatory=$true)] [DateTime] # Specifies date of information to be returned $QueryDate, [parameter(Mandatory=$true)] [String] # Specifies user to run report on $User, [String] # Specify server to query (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>$_lastEvent)]]" } 3 { $ReturnQuery += $tempString -f "4778", "and *[System[(EventRecordID>$_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
要运行此脚本,请执行以下操作 –
.\Get-TSUserReport.ps1 -ShowGraph -QueryDate "4/11/2012" -User jdoe