Назад | Перейти на главную страницу

Невозможно выйти, отключить или сбросить пользователя сервера терминалов в производственной среде

Я ищу некоторые идеи о том, как отключиться, выйти из системы или сбросить сеанс пользователя на сервере терминалов 2008 года (невозможно войти в систему как пользователь, так как он полностью заблокирован). Это производственная среда, поэтому о перезагрузке сервера или каких-либо общесистемных действиях пока не может быть и речи. Какие уловки Powershell помогут нам в этом?

Мы пытались отключиться, выйти из системы и сбросить сеанс, а также убить процессы сеанса, прямо с того же сервера терминалов (из диспетчера задач, диспетчера служб терминалов и монитора ресурсов), но безрезультатно.

Помогите!


ОБНОВЛЕНИЕ: мы закончили перезагрузку сервера, поскольку никакие другие попытки, о которых мы могли думать, не работали. Я оставлю этот вопрос открытым, надеясь, что у кого-то может быть больше информации об этой проблеме и ее возможных решениях.

Что помогло мне решить эту же проблему, так это убить все процессы, запущенные под заблокированной учетной записью из-под диспетчера задач, а затем я смог просто выйти из этой учетной записи (из учетной записи администратора).

Затем пользователь смог снова войти в систему под учетной записью.

Никакой перезагрузки и загрузки стороннего программного обеспечения не требовалось.

Хочу поделиться как я сбросил аккаунт без перезагрузки сервера. Прежде всего, вам необходимо иметь доступ администратора к серверу. Я использую следующий вариант входа в систему: mstsc / v:название сервера / console / admin для доступа к серверу. Затем в "Windows Taks Manager" перейдите в Пользователи и щелкните правой кнопкой мыши учетную запись, для которой вы хотите «выйти из системы», выберите «выйти из системы». Это должно освободить заблокированный сеанс, используемый этой учетной записью.

Простой ответ - запустить командную строку с повышенными привилегиями и ввести «Taskmgr», после чего вы сможете выйти из сеансов на вкладке ПОЛЬЗОВАТЕЛИ. Это не будет работать, если вы не находитесь в сеансе с повышенными правами.

У нас была аналогичная проблема с нашим сервером удаленного рабочего стола Windows Server 2008 R2. При просмотре RDS Manager пользовательский сеанс показал «Активный», но не имел соответствующего идентификатора сеанса № или подключенного устройства (оба были пустыми).

Все описанные выше приемы не помогли решить проблему. При подключении в качестве пользователя, о котором идет речь, появилось сообщение об ошибке, в котором говорилось, что сервер терминалов был занят, и чтобы повторить попытку позже или обратитесь к администратору.

Мы также перезагрузили сервер.

Полагаю, сегодня то же самое произошло с моим терминальным сервером Win2008R2. Симптомы были: 1. Он позвонил мне с сообщением «соединение просто висит навсегда». Он простой пользователь, поэтому я не могу ожидать подробного описания проблемы. 2. Пробовал выйти из системы / сбросить сеанс (что обычно помогает в этих случаях) - не сработало. Сеанс по-прежнему висит в списке со статусом «отключен». 3. Пытался убить все процессы для этого пользователя - не помогло. Сессия сохраняется и отказывается убиваться.

Решение было - подключитесь как пользователь (войдите с его учетными данными, если вы можете сбросить его пароль или использовать какую-либо удаленную помощь, чтобы увидеть, что происходит на его компьютере) и посмотрите, что происходит в окне входа в систему. При подключении я нажал кнопку «Подробности» RDP-клиента - и вот оно, сообщение об ошибке, что winlogon сделал что-то не так, он ждал, пока пользователь нажмет кнопку «повторить / игнорировать / и т. Д.», И так как это всемогущий winlogon он вызвал все это странное поведение.

p.s. Я не мог найти способ действительно принудительно убить сеанс :(

Вы можете запустить cmd, сделать сеанс запроса, проверьте идентификатор сеанса, который нужно убить, а затем выполните сбросить сеанс. Например, если с сеанс запроса вы получаете, что имя сеанса rdp-tcp # 1 - это то, которое вы хотите убить, тогда вы можете выполнить сбросить сеанс rdp-tcp # 1 и убить его.

У меня была такая же проблема в Windows Server 2016. Пользователь не смог войти в систему.

Поэтому я попробовал следующие шаги, чтобы отключить потерянный сеанс:

  1. на CLI Qwinsta перечисляет все доступные сеансы, неактивные и активные, есть один отключенный сеанс (на снимке экрана он называется «getr.») без имени пользователя, но с идентификатором сеанса.

показать активные сессии и убить их

  1. с идентификатором сеанса (7) из 1. Я пытался убить этот сеанс с помощью сброс сеанса 7 (к сведению: Rwinsta это псевдоним для сеанса сброса)

  2. он работал в течение одного сеанса, но в следующий раз это просто не повлияло, поэтому я открыл диспетчер задач и вкладку пользователя. Там вы найдете один расширяемый список, назначенный каждому пользователю удаленного рабочего стола - в одном списке не было имени пользователя, и отображалось только 4 запущенных задачи.

  3. Я попробовал очевидный вариант: выход пользователя из системы. Без всякого эффекта.

пытается выйти из системы

  1. Итак, я попытался завершить эти 4 задачи, назначенные этому пользователю. Будьте осторожны, потому что некоторые задачи, в первую очередь csrss.exe, при закрытии также могут привести к перезагрузке системы. Я их пропустил и просто убил несколько очевидных RDP-задач.

После Step / Try 4 даже последний сбойный сеанс был прерван, и пользователь смог снова войти в систему

  1. Если это все еще не работает, попробуйте это решение из Другой вопрос: Когда вы подключаетесь к RDP-клиенту, нажмите его кнопку «Детали». Там вы должны увидеть ошибку и даже можете нажать повторить попытку или игнорировать.

Этот сценарий Power-Shell работал у меня, он даже дает хороший файл журнала. Я получил это от Вот.: Я надеюсь, что это поможет кому-то другому, поскольку у других ответов было много предпосылок и / или они не работали для меня.

    # .SYNOPSIS
    #   Checks for disconnected sessions and logs off the disconnected user sessions.

    #.DESCRIPTION
    #   Checks for disconnected sessions and logs off the disconnected user sessions.

    #.NOTES
    #   File Name: Logoff-DisconnectedSession.ps1
    #   Author   : Bart Kuppens
    #   Version  : 1.1

    #.EXAMPLE
    #   PS > .\Logoff-DisconnectedSession.ps1


    function Ensure-LogFilePath([string]$LogFilePath)
    {
     if (!(Test-Path -Path $LogFilePath)) {New-Item $LogFilePath -ItemType directory >> $null}
    }

    function Write-Log([string]$message)
    {
       Out-File -InputObject $message -FilePath $LogFile -Append
    }

    function Get-Sessions
    {
       $queryResults = query session
       $starters = New-Object psobject -Property @{"SessionName" = 0; "UserName" = 0; "ID" = 0; "State" = 0; "Type" = 0; "Device" = 0;}
       foreach ($result in $queryResults)
       {
          try
          {
             if($result.trim().substring(0, $result.trim().indexof(" ")) -eq "SESSIONNAME")
             {
                $starters.UserName = $result.indexof("USERNAME");
                $starters.ID = $result.indexof("ID");
                $starters.State = $result.indexof("STATE");
                $starters.Type = $result.indexof("TYPE");
                $starters.Device = $result.indexof("DEVICE");
                continue;
             }

             New-Object psobject -Property @{
                "SessionName" = $result.trim().substring(0, $result.trim().indexof(" ")).trim(">");
                "Username" = $result.Substring($starters.Username, $result.IndexOf(" ", $starters.Username) - $starters.Username);
                "ID" = $result.Substring($result.IndexOf(" ", $starters.Username), $starters.ID - $result.IndexOf(" ", $starters.Username) + 2).trim();
                "State" = $result.Substring($starters.State, $result.IndexOf(" ", $starters.State)-$starters.State).trim();
                "Type" = $result.Substring($starters.Type, $starters.Device - $starters.Type).trim();
                "Device" = $result.Substring($starters.Device).trim()
             }
          } 
          catch 
          {
             $e = $_;
             Write-Log "ERROR: " + $e.PSMessageDetails
          }
       }
    }

    Ensure-LogFilePath($ENV:LOCALAPPDATA + "\DisconnectedSessions")
    $LogFile = $ENV:LOCALAPPDATA + "\DisconnectedSessions\" + "sessions_" + $([DateTime]::Now.ToString('yyyyMMdd')) + ".log"

    [string]$IncludeStates = '^(Disc)$'
    Write-Log -Message "Disconnected Sessions CleanUp"
    Write-Log -Message "============================="
    $DisconnectedSessions = Get-Sessions | ? {$_.State -match $IncludeStates -and $_.UserName -ne ""} | Select ID, UserName
    Write-Log -Message "Logged off sessions"
    Write-Log -Message "-------------------"
    foreach ($session in $DisconnectedSessions)
    {
       logoff $session.ID
       Write-Log -Message $session.Username
    }
    Write-Log -Message " "
    Write-Log -Message "Finished"  

Редактировать:
Первоначально я использовал этот сценарий для выхода из системы и закрытия всех «отключенных» сеансов. У нас есть несколько приложений терминального сервера с большим количеством пользователей и ограниченными лицензиями. Отключенные сеансы оставались открытыми в течение очень долгого времени, а иногда и оставались открытыми бесконечно. Это привело к появлению неиспользуемых сеансов, которые потребовали бы некоторых лицензий, и в результате другие пользователи не смогли бы подключиться.

  • Я запускаю скрипт, используя запланированное задание, чтобы регулярно проверять и
    отключать сеансы на некоторых моих серверах. Работает автономно
    без какого-либо взаимодействия.
  • Я использую его в операционных системах Windows 2008 R2 Server и Windows 2012 R2 Server.
  • Он закрывает только сеансы, которые были отключены.
  • Он обновляет файл журнала с пользователями или сеансами, которые он отключил.
  1. Найдите идентификатор сеанса с помощью qwinsta.
  2. Убить все процессы в рамках сеанса taskkill /FI "SESSION eq 1" /F, предполагая, что идентификатор сеанса, который вы хотите завершить, был возвращен qwinsta равным 1.

Это работало на Server 2012 Version 6.2 Build 9200, я ожидал, что он будет работать на всех версиях Windows.

Создайте файл в блокноте и назовите его findsession.cmd. Поместите команду Query Session / server:название сервера | найдите / i "% 1" и сохраните в каталог. Создайте еще один файл с именем resetsession.cmd, введите команду Reset Session% 1 / server:% 2 и сохраните.

В командной строке перейдите в каталог, в котором вы сохранили эти файлы, и введите имя пользователя findsession (логин пользователя, которого вы пытаетесь найти). Нажмите Enter, и вы должны увидеть логин и идентификатор сеанса. Введите resetsession.cmd ID Servername, и он сбросит этот сеанс. Я использую его ежедневно, и он очень быстро находит пользователей и сбрасывает их сеансы.

Для меня сработало:

  • войти на сервер
  • открыть диспетчер задач
  • ищите пользователя на вкладке пользователя
  • щелкните правой кнопкой мыши, подключитесь, введите пароль пользователя, я увидел экран «Пожалуйста, подождите»
  • нажмите alt-tab, это отключило меня от сервера и также отключило пользователя

У меня была такая же ситуация: Windows Server 2008 R2 со службами удаленных рабочих столов, соединение RDP, настроенное для выхода пользователей из системы после того, как сеанс неактивен или отключен через 3 часа, и все же некоторые сеансы оставались заблокированными. Я попытался выйти из них с помощью диспетчера удаленного рабочего стола и qwinsta / quser, но безуспешно.

Вот как я это решил:

  1. Я нашел идентификатор сеанса с помощью qwinsta.
  2. Я нашел PID winlogon.exe для зависшей сессии с query process /ID:yourid.
  3. Я убил процесс с помощью taskkill /f /PID yourPID.

Путь к работе. Я хотел бы иначе найти решение, чтобы этого не произошло.

Возможно, стоит проверить, что у пользователя нет всплывающего окна учетных данных, скрытого за окном удаленного рабочего стола с помощью alt + tab.

У коллеги была такая же проблема; не мог выйти из системы или выполнить сброс, и все его процессы были остановлены вручную. Когда я попытался получить доступ к графическому интерфейсу системы, из которой он удаленно взаимодействовал, я обнаружил, что за удаленным сеансом скрывается ящик учетных данных.

У меня была эта проблема с заблокированными пользователями приложения удаленного рабочего стола. Я написал этот сценарий Powershell для запуска по расписанию, чтобы отключить пользователей, которые были отключены более 2 минут. Единственное, что требуется отредактировать, - это НАЗВАНИЕ СЕРВЕРА который я установил, чтобы исключить сервер брокера удаленного рабочего стола, однако вы можете исключить любой сервер, который вам нравится, или вообще ни один.

Кстати, мой сценарий написан для Windows Server 2012 R2 ...

Скрипт делает это:

  • Получает список всех пользовательских сеансов удаленного рабочего стола.
  • Игнорирует любые сеансы, в которых не указано "STATE_DISCONNECTED".
  • Игнорирует сервер брокера (или любой другой сервер)
  • Игнорирует любые сеансы без единого идентификатора сеанса
  • Игнорирует любые сеансы, для которых нет времени отключения
  • Для тех сеансов, у которых есть время отключения, он проверяет текущее время, и если разница во времени между текущим моментом и временем отключения превышает X минут (в данном случае 2), процесс winlogon завершается.
  • Он также пытается выдать команду выхода (это, скорее всего, завершится ошибкой после завершения процесса winlogon).

Меня устраивает! Надеюсь, это поможет кому-то другому! :)

CLS
$RD = Get-RDUserSession | select ServerName, UserName, SessionState, DisconnectTime, UnifiedSessionId, SessionId #Get details about the sessions
foreach ($item in $RD) {
    $UsessionID = $item.UnifiedSessionId -as [int] 
    $sessionID = $item.SessionId -as [int] 
    if ($item.SessionState -eq "STATE_DISCONNECTED" -and $item.ServerName -ne "SERVERNAME" -and $item.DisconnectTime -ne $null -and $item.UnifiedSessionId -ne $null){
        $TimeDiff = New-TimeSpan -start $item.DisconnectTime -end (Get-Date) #check time difference between disconnect time and now. If time is greater than 2 minutes....
        if ($TimeDiff.Minutes -gt 2) {
            #Kill winlogon session for the user
            Get-WmiObject -ComputerName $item.Servername -query "select * from win32_process where name='winlogon.exe'" | Where-Object {$_.SessionId -eq $SessionId} | %{$_.terminate()}
            #Log off user if session still exists (will fail if user kicked)
            Invoke-RDUserLogoff -HostServer $item.ServerName -UnifiedSessionID $UsessionID -Force -erroraction 'silentlycontinue'
            }
         }
      }

Или, если вы предпочитаете версию, в которой вы можете видеть, что происходит на экране:

 CLS
    $RD = Get-RDUserSession | select ServerName, UserName, SessionState, DisconnectTime, UnifiedSessionId, SessionId
    foreach ($item in $RD) {
        $UsessionID = $item.UnifiedSessionId -as [int]
        $sessionID = $item.SessionId -as [int]
        if ($item.SessionState -eq "STATE_DISCONNECTED" -and $item.ServerName -ne "SERVERNAME" -and $item.DisconnectTime -ne $null -and $item.UnifiedSessionId -ne $null){
            #On Screen Output
            write-host " Name : " $Item.UserName -ForegroundColor "yellow" -NoNewline
            write-host " Unified Session Id : " $UsessionID -ForegroundColor "darkcyan" -NoNewline
            write-host " User Session Id : " $sessionID -ForegroundColor "darkyellow" -NoNewline
            write-host " Session State : " $item.SessionState -ForegroundColor "magenta" -NoNewline
            write-host " Server : " $item.ServerName -ForegroundColor "cyan" -NoNewline
            write-host " Disconnect Time : " $item.DisconnectTime -ForegroundColor "gray" 
            #End On Screen Output
            $TimeDiff = New-TimeSpan -start $item.DisconnectTime -end (Get-Date)
            if ($TimeDiff.Minutes -lt 2) {
                write-host " Disconnected for less than 2 minutes" -ForegroundColor "Green"}
            else {
                write-host " Disconnected for more than 2 minutes" -ForegroundColor "Red" -BackgroundColor "darkyellow"
                write-host " Killing session : " $item.ServerName " ID : " $UsessionID $item.UserName -ForegroundColor "Red"
                #Kill Process "Winlogon.exe" for the user (this should kill the session)
                Get-WmiObject -ComputerName $item.Servername -query "select * from win32_process where name='winlogon.exe'" | Where-Object {$_.SessionId -eq $SessionId} | %{$_.terminate()}
                #Logout User (if session still exists)
                Invoke-RDUserLogoff -HostServer $item.ServerName -UnifiedSessionID $UsessionID -Force -erroraction 'silentlycontinue'
                Write-host " Done! " -ForegroundColor "Green" -BackgroundColor "blue"
                }
             }
          }

вы всегда можете использовать PowerShell со своего локального компьютера и делать это удаленно

Invoke-command -computername <servername> -Credential (get-credential) { 
    $session = ((quser | ? { $_ -match <username> }) -split ' +' )[2]
    logoff $session
} 

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

Вам нужно нажать на процесс и показать процесс от всех пользователей, после чего вы сможете отключиться.

почему бы не создать политику сеанса в разделе конфигурации узла сеанса удаленного рабочего стола, заканчивая отключенным или бездействующим сеансом после определенного интервала.

Не совсем та же среда (у нас 2012r2), но перезапуск службы управления виртуальными машинами Hyper-V (VMMS) освободил для меня соединение.

Вы можете скачать "Обозреватель процессов"от Microsoft и используйте его для решения своей проблемы. Если у вас есть идентификаторы сеанса, вы можете найти соответствующие процессы. Затем, если сеанс пользователя отключен, вы можете убить процесс с помощью Process Explorer.

Возможно, есть еще выполняющийся процесс, блокирующий процесс выхода. Проверьте все еще выполняющиеся процессы для затронутого пользователя. Затем убивайте процесс один за другим, чтобы увидеть, что одна из них вызывает проблему.

Также проверьте HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run Ключ реестра, который только необходим. Процессы запускаются. В 64bit это HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Run.

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

Вы пытались выйти из системы из диспетчера служб удаленных рабочих столов? Перейдите в Администрирование -> Службы удаленных рабочих столов -> Диспетчер служб удаленных рабочих столов и выйдите из сеанса. Это может сработать.

Перейдите в стартовое окно и щелкните свое имя

См. Образец здесь