Подтвердить что ты не робот

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

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

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

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

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

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

4b9b3361

Ответ 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>

Ответ 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

если сеансы не найдены: 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
    }