Требуется завершить работу всех пользователей на терминальном сервере в автоматическом режиме для проведения архивации. При решении простой на первый взгляд задачи проявилось столько нюансов, что решил оформить ее в виде форума.
Завершение работы всех пользователей (logoff all users)
Опубликованно: 05-04-2012
Есть статья 259436 от
Опубликовано пользователем manager
Есть статья 259436 от Микрософта. Вкратце советуют так:
query session >session.txt
for /f "skip=1 tokens=3," %%i in (session.txt) DO logoff %%i
На самом деле надо делать query user, так как session вернет лишние строки для services, console и rdp-tcp.
query user >session.txt
for /f "skip=1 tokens=3," %%i in (session.txt) DO logoff %%i
Исправленный вариант отработает для всех активных пользователей, но не сделает logoff для отключенных (disconnect).
отключение отключенных :)
Опубликовано пользователем manager
Анализируя в цикле файл session.txt мы используем ключ /f с параметрами skip=1 и tokens=3. Первый параметр указывает, что надо пропустить первую (заголовочную) строку, второй - указывает на выделение 3-ей подстроки в каждой последующей строке файла.
Строка активного пользователя имеет такой вид:
имя_пользователя имя_сессии идентификатор_сессии статус ...
Третьей подстрокой будет идентификатор сессии и все у нас правильно.
Но для отключенного пользователя ситуация другая:
имя_пользователя идентификатор_сессии статус ...
Третьей подстрокой в данном случае будет статус и команда logoff отработает с ошибкой.
Использовать имя пользователя
Опубликовано пользователем manager
Напрашивается решение использовать имя пользователя - первую подстроку. Но и тут не все благополучно, к имени пользователя под которым запущена команда Windows добавляет значок >
Стандартные способы обработки строк, например, %%i:~2% в цикле не работают. У меня точно не заработало, хотя потратил часа 2.
ну у меня получилось, вот
Опубликовано пользователем kenny_rim (не проверено)
ну у меня получилось, вот содержимое моего bat-файла:
query user >user.txt
for /f "skip=1 tokens=2," %%i in (user.txt) DO logoff %%i
т.е. он завершает или RDP-TCP# или код ID(там где пользователь отключен (disconnect))
единственный момент, в именах пользователей не должно быть пробелов(я их заменил на _) иначе неотработает.
В ковычки имена зикинь и
Опубликовано пользователем Асден (не проверено)
В ковычки имена зикинь и будет ок
Powershell
Опубликовано пользователем manager
Не получается в BAT попробуем в powershell. Почитав что уже есть наработанного удивленно увидел, что большинство скриптов базируется на той же самой quser (query user) Вывод команды сохраняется в строковый массив $users=quser и далее из строк извлекаются имена пользователей.
Все скрипты либо маленькие, но не учитывающие изменение строки для отключенного пользователя, либо далеки от прозрачности. В общем некрасивый, но выход.
Анализ процессов
Опубликовано пользователем manager
Вернемся к постановке задачи. Проводится архивация, ей могут помешать определенные приложения. То есть мы можем получить список процессов по условию, посмотреть под кем они запущены и завершить сеансы соответствующих пользователей.
Конкретный пример, завершение работы всех пользователей, от имени которых запущен "толстый клиент" 1с 8.2 (1cv8.exe)
$1cv8 = Get-WMIObject win32_process | where {$_.ProcessName -eq "1cv8.exe"}
foreach ($proc in $1cv8)
{
logoff $proc.SessionID
}
Комментарии излишни.
небольшая доработка
Опубликовано пользователем Антон (не проверено)
$nameproc = "1cv8s.exe","1cv8c.exe","1cv8.exe"
foreach ($name in $nameproc)
{
$1cv8 = Get-WMIObject win32_process | where {$_.ProcessName -eq $name}
if ($1cv8)
{
foreach ($proc in $1cv8)
{
logoff $proc.SessionID
}
}
}
Побочный эффект
Опубликовано пользователем manager
Экспериментируя с query session нашел интересный способ как одной командой отключить (не завершить работу) всех RDP пользователей от сервера.
Последняя строка отображает сессию rdp-tcp с идентификатором 65536. Эта сессия называется Listener она по умолчанию привязана к протоколу RDP и служит для создания пользовательских сессий RDP.
Если мы завершим ее, то произойдет отключение всех RDP сессий.
logoff 65536