Powershell 无法将变量解析到ForEach($Servers中的服务器)循环中?
我正在尝试更正下面的脚本,以便使用Qwinsta查询服务器登录会话 此服务器的目标是显示当前登录的用户 脚本主要部分: $queryResults=(qwinsta/server:$ServerName |选择对象-跳过1| ForEach对象{($u33; trim()-replace“\s+”,“,”)}从csv转换 -错误(操作停止) 工作正常吗Powershell 无法将变量解析到ForEach($Servers中的服务器)循环中?,powershell,Powershell,我正在尝试更正下面的脚本,以便使用Qwinsta查询服务器登录会话 此服务器的目标是显示当前登录的用户 脚本主要部分: $queryResults=(qwinsta/server:$ServerName |选择对象-跳过1| ForEach对象{($u33; trim()-replace“\s+”,“,”)}从csv转换 -错误(操作停止) 工作正常吗 PS C:\WINDOWS\system32> $queryResults services 0 Disc ---
PS C:\WINDOWS\system32> $queryResults
services 0 Disc
-------- - ----
console 1 Conn
Administrator 3 Disc
rdp-tcp 65536 Listen
脚本:
$HtmlHead = @"
<style>
body {
font-family: Arial;
}
table {
width: 100%;
border-collapse: collapse;
border: 1px solid;
}
th {
background-color: green;
border: 1px solid;
padding: 1px;
}
td {
border: 1px solid;
padding: 1px;
}
</style>
"@
$Today = Get-Date -Format 'F'
$SessionList = "`n`nRDP Session List - " + $Today + "`n`n"
$CurrentSN = 0
# Get a list of servers from Active Directory
write-progress -activity "Getting list of servers from Active Directory" -status "... please wait ..."
$Servers = Get-ADComputer -Filter { Enabled -eq $True -and OperatingSystem -like "*Server*" } -SearchBase "OU=Servers,DC=Company,DC=com," | Where-Object { Test-Connection $_.Name -Count 1 -Quiet } | Select-Object -ExpandProperty Name
$NumberOfServers = $Servers.Count
# Iterate through the retrieved list to check RDP sessions on each machine
ForEach ($Server in $Servers) {
$ServerName = $Server.Name
Write-Host "Processing $($Server.Name) ..." -ForegroundColor Yellow
Write-progress -activity "Checking RDP Sessions" -status "Querying $ServerName" -percentcomplete (($CurrentSN / $NumberOfServers) * 100)
# Run qwinsta and grab the output
try {
$queryResults = (qwinsta /server:$ServerName | Select-Object -Skip 1 | ForEach-Object { (($_.trim() -replace "\s+", ",")) } | convertfrom-csv -ErrorAction Stop)
# get session info from the instance
ForEach ($QueryResult in $QueryResults) {
$RDPUser = $($QueryResult.substring(19, 22)).trim()
$SessionType = $($QueryResult.substring(1, 18)).trim()
$SessionID = $($QueryResult.substring(41, 5)).trim()
$ReturnedCurrentState = $($QueryResult.substring(48, 8)).trim()
$RDPUser = $QueryResult.USERNAME
$SessionType = $QueryResult.SESSIONNAME
$SessionID = $QueryResult.ID
$ReturnedCurrentState = $QueryResult.State
If ($ReturnedCurrentState -eq $null) { $CurrentState = "Disconnected" } Else { $CurrentState = "Active" }
# filter out the irrelevant information
If (($RDPUser -ne $null) -and ($SessionType -ne "console") -and ($SessionType -ne "services") -and ($SessionType -ne "rdp-tcp") -and ($RDPUser -ne "65536")) {
$SessionList = $SessionList + "`n" + $ServerName + " logged in by " + $RDPUser + " on " + $SessionType + ", session id $SessionID $CurrentState"
}
}
}
catch {
$SessionList = $SessionList + "`n Unable to query " + $ServerName
write-host "Unable to query $ServerName!" -foregroundcolor Red
}
$CurrentSN++
}
# Send the output the screen.
$SessionList + "`n`n"
$sendMailArgs = @{
From = "$env:USERNAME@$env:userdnsdomain"
To = 'SOC@domain.com'
SmtpServer = 'SMTP.domain.com'
Priority = 'High'
BodyAsHtml = $true
Body = ($SessionList | ConvertTo-Html -Head $HtmlHead) -join "`r`n"
Subject = "$($SessionList.Count) Logged On users from $($NumberOfServers) online servers as at $($Today)"
}
Send-MailMessage @sendMailArgs
电子邮件结果通常如下所示:
*
424
这是什么意思?最有可能的是Substring()方法引发异常,因为startIndex参数值41和48似乎很大。如果$QueryResult字符串变短,您将得到该异常并立即移动到catch语句
我建议将查询服务器和构建会话列表的错误处理分开
更新:
下面是如何在脚本示例中分离错误处理。基本上,您需要了解一些方法或cmdlet,这些方法或cmdlet理论上可以使用您提供的输入参数引发异常,并涵盖这些情况
ForEach ($Server in $Servers) {
$ServerName = $Server.Name
Write-Host "Processing $ServerName ..." -ForegroundColor Yellow
Write-progress -activity "Checking RDP Sessions" -status "Querying $ServerName" -percentcomplete (($CurrentSN / $NumberOfServers) * 100)
# Run qwinsta and grab the output
try {
$queryResults = (qwinsta /server:$ServerName | Select-Object -Skip 1 | ForEach-Object { (($_.trim() -replace "\s+", ",")) } | convertfrom-csv )
}
catch {
# Error handling for failed server connection here
$SessionList += "`n Unable to query " + $ServerName
write-host "Unable to query $ServerName!" -foregroundcolor Red
continue # Skip to next $Server
}
# get session info from the instance
ForEach ($QueryResult in $QueryResults) {
try {
# Do something about this
$RDPUser = $($QueryResult.substring(19, 22)).trim()
$SessionType = $($QueryResult.substring(1, 18)).trim()
$SessionID = $($QueryResult.substring(41, 5)).trim()
$ReturnedCurrentState = $($QueryResult.substring(48, 8)).trim()
$RDPUser = $QueryResult.USERNAME
$SessionType = $QueryResult.SESSIONNAME
$SessionID = $QueryResult.ID
$ReturnedCurrentState = $QueryResult.State
}
catch {
# Insert your error handling here
# Write-Host "Failed to process query result from $ServerName!" -foregroundcolor Red
Write-Host $Error[0].Exception # If you want to get the exception message. A shorter way to do it below
# Write-Host $_
}
If ($null -eq $ReturnedCurrentState) { $CurrentState = "Disconnected" } Else { $CurrentState = "Active" }
# filter out the irrelevant information
If (($null -ne $RDPUser) -and ($SessionType -ne "console") -and ($SessionType -ne "services") -and ($SessionType -ne "rdp-tcp") -and ($RDPUser -ne "65536")) {
$SessionList = $SessionList + "`n" + $ServerName + " logged in by " + $RDPUser + " on " + $SessionType + ", session id $SessionID $CurrentState"
}
}
$CurrentSN++
}
我真正关心的是代码块,在代码块中,您为变量赋值,如
$RDPUser
,$SessionType
,等等。我会告诉您,我不知道您的环境,但逻辑看起来非常奇怪。如果$QueryResult
是一个具有多个属性的对象,为什么要使用子字符串?对象没有此方法。如果它只是一个在某些字符位置具有值的长字符串,为什么要尝试获取它的属性值,如$QueryResult.ID
-它没有任何。根据请求进行更新。添加以查看异常错误消息。是的,我已经包含了try/CatchSure,但catch块对异常没有任何作用。了解如何查看异常的实际情况。感谢您的建议,您能告诉我如何在多个Try/Catch嵌套上执行此操作吗?当然,我已经用一个示例更新了我的原始答案。太好了,非常感谢您对思考过程的详细解释和分享,这对我回答这个问题很有帮助。
ForEach ($Server in $Servers) {
$ServerName = $Server.Name
Write-Host "Processing $ServerName ..." -ForegroundColor Yellow
Write-progress -activity "Checking RDP Sessions" -status "Querying $ServerName" -percentcomplete (($CurrentSN / $NumberOfServers) * 100)
# Run qwinsta and grab the output
try {
$queryResults = (qwinsta /server:$ServerName | Select-Object -Skip 1 | ForEach-Object { (($_.trim() -replace "\s+", ",")) } | convertfrom-csv )
}
catch {
# Error handling for failed server connection here
$SessionList += "`n Unable to query " + $ServerName
write-host "Unable to query $ServerName!" -foregroundcolor Red
continue # Skip to next $Server
}
# get session info from the instance
ForEach ($QueryResult in $QueryResults) {
try {
# Do something about this
$RDPUser = $($QueryResult.substring(19, 22)).trim()
$SessionType = $($QueryResult.substring(1, 18)).trim()
$SessionID = $($QueryResult.substring(41, 5)).trim()
$ReturnedCurrentState = $($QueryResult.substring(48, 8)).trim()
$RDPUser = $QueryResult.USERNAME
$SessionType = $QueryResult.SESSIONNAME
$SessionID = $QueryResult.ID
$ReturnedCurrentState = $QueryResult.State
}
catch {
# Insert your error handling here
# Write-Host "Failed to process query result from $ServerName!" -foregroundcolor Red
Write-Host $Error[0].Exception # If you want to get the exception message. A shorter way to do it below
# Write-Host $_
}
If ($null -eq $ReturnedCurrentState) { $CurrentState = "Disconnected" } Else { $CurrentState = "Active" }
# filter out the irrelevant information
If (($null -ne $RDPUser) -and ($SessionType -ne "console") -and ($SessionType -ne "services") -and ($SessionType -ne "rdp-tcp") -and ($RDPUser -ne "65536")) {
$SessionList = $SessionList + "`n" + $ServerName + " logged in by " + $RDPUser + " on " + $SessionType + ", session id $SessionID $CurrentState"
}
}
$CurrentSN++
}