Удаленный сеанс удаленного доступа Powershell

Я пытаюсь сформулировать команду Powershell для удаленного выхода из системы. У нас есть терминальный сервер с очень неустойчивой программой, которая иногда блокирует сеансы. Мы должны удаленно выходить из системы, но я пытаюсь написать оператор Powershell, который выйдет из системы, который запускает скрипт. Я разобрался и нашел эту команду:

Invoke-Command -ComputerName MyServer -Command {shutdown -l} 

Однако команда возвращает «неправильную функцию». Я могу успешно запускать другие команды в скобках, например Get-Process.

Идея заключается в том, чтобы я включил ее в сценарий, который пользователи могут запускать для выхода из сервера (поскольку, когда он блокируется, они не могут получить доступ к меню «Пуск» или ALT + CTRL + END, чтобы сделать это через графический интерфейс).

Поток будет следующим: Боб входит в MyServer через RDP, но его сеанс замерзает. На своем локальном рабочем столе он может запускать MyScript (содержащий команду, аналогичную приведенной выше), которая выйдет из сеанса на MyServer.

Возможно, вы можете выйти из системы с помощью команды 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 

Вот отличное скриптовое решение для удаленного доступа или локализации пользователей. Я использую 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 } } 

В первой строке этого скрипта присвойте $ serverName соответствующее значение или localhost, если он выполняется локально. Я использую этот скрипт для загрузки пользователей, прежде чем автоматический процесс попытается переместить некоторые папки. Предотвращает ошибки «файл в использовании» для меня. Еще одно замечание: этот скрипт должен запускаться как пользователь-администратор, иначе вы можете получить доступ к нему, отказавшему в попытке зарегистрировать кого-то. Надеюсь это поможет!

Добавление простых команд 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 

Это oldschool и предшествует PowerShell, но я использовал компиляцию qwinsta / rwinsta для YEARS для удаленного выхода из устаревших сеансов RDP. Он встроен, по крайней мере, в Windows XP и вперёд (возможно, раньше)

Определите идентификатор сеанса:

 qwinsta /SERVER: 

Удалите сеанс, о котором идет речь:

 rwinsta  /SERVER: 

Попробуйте модуль служб терминалов PowerShell :

 Get-TSSession -ComputerName comp1 -UserName user1 | Stop-TSSession -Force 

Вы можете использовать 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. Выполнить как ад.

Я изменил ответ Кейси только на отключенные сеансы выхода из системы, выполнив следующие действия:

  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 {} } 

Выйдите из системы всеми пользователями:

 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 элементов в зависимости от того, подключены ли пользователи или отключены от сеанса терминала

Поскольку мы находимся в области PowerShell, это очень полезно, если мы можем вернуть правильный объект PowerShell …

Мне лично нравится этот метод parsingа, для терпения:

 ((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 

Я делаю шаг дальше и даю вам очень чистый объект в своем блоге.

Ниже сценария будет хорошо работать как для активных, так и для отключенных сеансов, если пользователь имеет доступ к удаленному запуску команды logoff. Все, что вам нужно сделать, это изменить имя сервера из «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!" 

Некоторые выборочные выходы. Для активного сеанса: введите описание изображения здесь

Для отключенных сеансов: введите описание изображения здесь

если сеансов не найдено: введите описание изображения здесь Проверьте это решение, чтобы запросить все серверы AD для вашего имени пользователя и выхода из системы только отключенных сеансов. Сценарий также скажет вам, произошла ли ошибка подключения или запроса сервера.

Powershell, чтобы выяснить отключенную сессию RDP и выйти из системы одновременно

Давайте будем гением компьютера.