Удаленный сеанс удаленного доступа Powershell
Я пытаюсь сформулировать команду Powershell для удаленного выхода из системы. У нас есть терминальный сервер с очень неустойчивой программой, которая иногда блокирует сеансы. Мы должны удаленно выйти из системы, но я пытаюсь написать оператор Powershell, который выйдет из системы, который запустил script. Я разобрался и нашел эту команду:
Invoke-Command -ComputerName MyServer -Command {shutdown -l}
Однако команда возвращает "неправильную функцию". Я могу успешно запускать другие команды в скобках, например Get-Process.
Идея заключается в том, чтобы я помещал это в script, который пользователи могут запускать, чтобы выходить из системы с сервера (поскольку, когда он блокируется, они не могут получить доступ к меню запуска или ALT + CTRL + END, чтобы сделать это через GUI).
Поток будет следующим:
Боб записывается на MyServer через RDP, но его сеанс замерзает. На своем локальном рабочем столе он может запускать MyScript (содержащий команду, аналогичную описанной выше), которая выйдет из сеанса на MyServer.
Ответы
Ответ 1
Возможно, удивительно, что вы можете выйти из системы с помощью команды logoff
.
C:\> logoff /?
Terminates a session.
LOGOFF [sessionname | sessionid] [/SERVER:servername] [/V] [/VM]
sessionname The name of the session.
sessionid The ID of the session.
/SERVER:servername Specifies the Remote Desktop server containing the user
session to log off (default is current).
/V Displays information about the actions performed.
/VM Logs off a session on server or within virtual machine.
The unique ID of the session needs to be specified.
Идентификатор сеанса можно определить с помощью команд qwinsta
(query session
) или quser
(query user
) (см. здесь):
$server = 'MyServer'
$username = $env:USERNAME
$session = ((quser /server:$server | ? { $_ -match $username }) -split ' +')[2]
logoff $session /server:$server
Ответ 2
Здесь вы найдете отличное решение для регистрации пользователей удаленно или локально. Я использую qwinsta для получения информации о сеансе и построения массива из данного вывода. Это позволяет легко перебирать каждую запись и выходить из системы только с фактическими пользователями, а не с самим системным или RDP-слушателем, который обычно просто выдает ошибку отказа в доступе.
$serverName = "Name of server here OR localhost"
$sessions = qwinsta /server $serverName| ?{ $_ -notmatch '^ SESSIONNAME' } | %{
$item = "" | Select "Active", "SessionName", "Username", "Id", "State", "Type", "Device"
$item.Active = $_.Substring(0,1) -match '>'
$item.SessionName = $_.Substring(1,18).Trim()
$item.Username = $_.Substring(19,20).Trim()
$item.Id = $_.Substring(39,9).Trim()
$item.State = $_.Substring(48,8).Trim()
$item.Type = $_.Substring(56,12).Trim()
$item.Device = $_.Substring(68).Trim()
$item
}
foreach ($session in $sessions){
if ($session.Username -ne "" -or $session.Username.Length -gt 1){
logoff /server $serverName $session.Id
}
}
В первой строке этого script укажите $serverName соответствующее значение или localhost, если оно выполняется локально. Я использую этот script для запуска пользователей, прежде чем автоматический процесс попытается переместить некоторые папки. Предотвращает ошибки "файл в использовании" для меня. Еще одно замечание: этот script должен запускаться как пользователь-администратор, иначе вы можете получить доступ к нему, отказавшему в попытке зарегистрировать кого-то. Надеюсь, это поможет!
Ответ 3
Добавление простых команд DOS, если кто-то настолько склонен. Да, это все еще работает для Win 8 и Server 2008 + Server 2012.
Query session /server:Server100
Вернется:
SESSIONNAME USERNAME ID STATE TYPE DEVICE
rdp-tcp#0 Bob 3 Active rdpwd
rdp-tcp#5 Jim 9 Active rdpwd
rdp-tcp 65536 Listen
Чтобы выйти из сеанса, используйте:
Reset session 3 /server:Server100
Ответ 4
Это oldschool и предшествует PowerShell, но я использовал компиляцию qwinsta/rwinsta для YEARS для удаленного выхода из устаревших сеансов RDP. Он встроен, по крайней мере, в Windows XP и вперёд (возможно, раньше)
Определите идентификатор сеанса:
qwinsta /SERVER:<NAME>
Удалите указанный сеанс:
rwinsta <SESSION_ID> /SERVER:<NAME>
Ответ 5
Попробуйте Модуль служб терминалов PowerShell:
Get-TSSession -ComputerName comp1 -UserName user1 | Stop-TSSession -Force
Ответ 6
Вы можете использовать Invoke-RDUserLogoff
Пример: отключение пользователей Active Directory определенного организационного подразделения:
$users = Get-ADUser -filter * -SearchBase "ou=YOUR_OU_NAME,dc=contoso,dc=com"
Get-RDUserSession | where { $users.sAMAccountName -contains $_.UserName } | % { $_ | Invoke-RDUserLogoff -Force }
В конце канала, если вы попытаетесь использовать только foreach (%), он отключит только одного пользователя. Но используя эту комбинацию foreach и pipe:
| % {$ _ | команда}
будет работать как ожидалось.
Ps. Запуск от имени пользователя.
Ответ 7
Я изменил ответ Кейси только для отключенных сеансов выхода из системы, выполнив следующие действия:
foreach($Server in $Servers) {
try {
query user /server:$Server 2>&1 | select -skip 1 | ? {($_ -split "\s+")[-5] -eq 'Disc'} | % {logoff ($_ -split "\s+")[-6] /server:$Server /V}
}
catch {}
}
Ответ 8
Отключить всех пользователей с компьютера:
try {
query user /server:$SERVER 2>&1 | select -skip 1 | foreach {
logoff ($_ -split "\s+")[-6] /server:$SERVER
}
}
catch {}
Подробнее:
-
try
/catch
используется, когда на сервере нет пользователей, а query
возвращает ошибку. однако вы можете отбросить часть 2>&1
и удалить try
/catch
, если не хотите видеть строку с ошибкой
-
select -skip 1
удаляет строку заголовка
- внутренний
foreach
отходит от каждого пользователя
-
($_ -split "\s+")
разделяет строку на массив с помощью только текстовых элементов
-
[-6]
index получает идентификатор сеанса и является 6-м строковым подсчетом с обратной стороны массива, вам нужно сделать это, потому что вывод query
будет содержать 8 или 9 элементов в зависимости от того, подключены ли пользователи или отключены от терминальная сессия
Ответ 9
Поскольку мы находимся в области PowerShell, будет очень полезно, если мы сможем вернуть правильный объект PowerShell...
Мне лично этот метод разбора нравится, для краткости
((quser) -replace '^>', '') -replace '\s{2,}', ',' | ConvertFrom-Csv
Примечание: это не относится к отключенным ("дисковым") пользователям, но работает хорошо, если вы просто хотите получить быстрый список пользователей и не заботитесь об остальной информации. Я просто хотел список, и мне было все равно, если они были отключены.
Если вы заботитесь об остальных данных, они будут немного сложнее:
(((quser) -replace '^>', '') -replace '\s{2,}', ',').Trim() | ForEach-Object {
if ($_.Split(',').Count -eq 5) {
Write-Output ($_ -replace '(^[^,]+)', '$1,')
} else {
Write-Output $_
}
} | ConvertFrom-Csv
Я сделаю еще один шаг и дам вам очень чистый объект в моем блоге.
Ответ 10
Приведенный ниже сценарий будет хорошо работать как для активных, так и для отключенных сеансов, если у пользователя есть доступ к удаленному запуску команды выхода из системы. Все, что вам нужно сделать, это изменить имя сервера с "YourServerName" на 4-й строке.
param (
$queryResults = $null,
[string]$UserName = $env:USERNAME,
[string]$ServerName = "YourServerName"
)
if (Test-Connection $ServerName -Count 1 -Quiet) {
Write-Host "'n'n'n$ServerName is online!" -BackgroundColor Green -ForegroundColor Black
Write-Host ("'nQuerying Server: '"$ServerName'" for disconnected sessions under UserName: '"" + $UserName.ToUpper() + "'"...") -BackgroundColor Gray -ForegroundColor Black
query user $UserName /server:$ServerName 2>&1 | foreach {
if ($_ -match "Active") {
Write-Host "Active Sessions"
$queryResults = ("'n$ServerName," + (($_.trim() -replace ' {2,}', ','))) | ConvertFrom-Csv -Delimiter "," -Header "ServerName","UserName","SessionName","SessionID","CurrentState","IdealTime","LogonTime"
$queryResults | ft
Write-Host "Starting logoff procedure..." -BackgroundColor Gray -ForegroundColor Black
$queryResults | foreach {
$Sessionl = $_.SessionID
$Serverl = $_.ServerName
Write-Host "Logging off"$_.username"from $serverl..." -ForegroundColor black -BackgroundColor Gray
sleep 2
logoff $Sessionl /server:$Serverl /v
}
}
elseif ($_ -match "Disc") {
Write-Host "Disconnected Sessions"
$queryResults = ("'n$ServerName," + (($_.trim() -replace ' {2,}', ','))) | ConvertFrom-Csv -Delimiter "," -Header "ServerName","UserName","SessionID","CurrentState","IdealTime","LogonTime"
$queryResults | ft
Write-Host "Starting logoff procedure..." -BackgroundColor Gray -ForegroundColor Black
$queryResults | foreach {
$Sessionl = $_.SessionID
$Serverl = $_.ServerName
Write-Host "Logging off"$_.username"from $serverl..."
sleep 2
logoff $Sessionl /server:$Serverl /v
}
}
elseif ($_ -match "The RPC server is unavailable") {
Write-Host "Unable to query the $ServerName, check for firewall settings on $ServerName!" -ForegroundColor White -BackgroundColor Red
}
elseif ($_ -match "No User exists for") {Write-Host "No user session exists"}
}
}
else {
Write-Host "'n'n'n$ServerName is Offline!" -BackgroundColor red -ForegroundColor white
Write-Host "Error: Unable to connect to $ServerName!" -BackgroundColor red -ForegroundColor white
Write-Host "Either the $ServerName is down or check for firewall settings on server $ServerName!" -BackgroundColor Yellow -ForegroundColor black
}
Read-Host "'n'nScript execution finished, press enter to exit!"
Некоторые примеры выходов. Для активного сеанса: ![enter image description here]()
Для отключенных сеансов: ![enter image description here]()
если сеансы не найдены:
Проверьте это решение, а также запросите у всех серверов AD ваше имя пользователя и выйдите из системы только для отключенных сеансов. Сценарий также сообщит вам, если произошла ошибка при подключении или запросе к серверу.
Powershell для обнаружения отключенного сеанса RDP и одновременного выхода из системы
Ответ 11
Я уверен, что мой код будет проще и работает быстрее.
$logon_sessions = get-process -includeusername | Select-Object -Unique -Property UserName, si | ? { $_ -match "server" -and $_ -notmatch "admin" }
foreach ($id in $logon_sessions.si) {
logoff $id
}