Windows: узнаём, кто где залогинен

Windows: узнаём, кто где залогинен
— Ой, у меня ничего не работает, помогите!
— Не переживайте, сейчас всё исправим. Назовите имя компьютера…
(классика жанра из звонков в техподдержку)

Хорошо, если у вас есть инструмент а-ля BgInfo или ваши пользователи знают про шорткат Windows+Pause/Break и умеют его нажимать. Встречаются даже редкие экземпляры, которые успели выучить имя своей машины. Но часто у звонящего вдобавок к его основной проблеме появляется вторая: узнать имя/IP-адрес компьютера. И нередко на решение этой второй проблемы уходит куда больше времени, чем первой (а надо было всего лишь обои поменять или вернуть пропавший ярлык :).
А ведь намного приятнее услышать что-то вроде:
— Татьяна Сергеевна, не беспокойтесь, уже подключаюсь…


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

  1. BgInfo, Desktop Info и им подобные. Если много денег, есть и платные. Суть в том, что на десктоп выводится техническая информация: имя машины, IP-адрес, логин и т.д. В Desktop Info можно даже графики производительности запилить на половину экрана.
    Не устраивает то, что для того же Bginfo, например, пользователю нужно сворачивать окна, чтобы увидеть нужные данные. Еще мы с коллегами не раз наблюдали у BgInfo характерный артефакт, когда новый текст выводится поверх старого.
    Некоторых пользователей раздражает тот факт, что админы рисуют пугающее 192.168.0.123 на мордочке растянувшегося на рабочем столе котика портят эстетику фоновой картинки, и, разумеется, это жутко демотивирует и напрочь убивает рабочий настрой.
  2. Ярлык а-ля «Кто я» (не пытайтесь добавить ему знак вопроса в конце :). Классический ярлык на рабочем столе, за которым прячется аккуратный или не очень скрипт, выводящий нужную информацию в виде диалогового окна. Иногда вместо ярлыка на рабочий стол кладут сам скрипт, что ИМХО моветон.
    Недостаток в том, что для запуска ярлыка, как и в первом случае, нужно сворачивать все открытые окна (баловней судьбы, у которых на рабочей машине открыто единственное окно с пасьянсом, в расчет не берём). Кстати, а ваши пользователи знают, куда нужно тыкнуть, чтобы свернуть все окна? Правильно, пальцем в глаз админу.

Также кэп подсказывает, что у обоих описанных выше способов основной недостаток в том, что в получении информации участвует пользователь, который может быть подслеповат, глуп и вообще соврать.
Вариант с повышением компьютерной грамотности, когда все знают, где в Windows смотреть имя своей машины, рассматривать не буду: дело благородное, но очень трудное. А если в компании текучка кадров, то и вовсе гиблое. Что там говорить, в большинстве случаев и логин-то свой не помнят.

Душу излил, а теперь к делу.
За основу была взята идея хабровчанина mittel из этой статьи.
Суть задумки в том, что при входе пользователя в Windows логон-скрипт заносит нужную информацию (время и имя машины) в определенный атрибут учётной записи пользователя. А при выходе из системы отрабатывает аналогичный логофф-скрипт.

Сама идея мне понравилась, а вот в реализации кое-что не устроило.

  1. Групповая политика, в которой прописаны логон- и логофф-скрипты для пользователей, применяется ко всему домену, поэтому скрипты будут отрабатывать на любой машине, на которую логинятся пользователи. Если у вас наряду с рабочими станциями используются терминальные решения (например, Microsoft RDS или продукты Citrix), такой подход будет неудобным.
  2. Данные заносятся в атрибут Department учетной записи пользователя, на который у рядового пользователя есть доступ только на чтение. Помимо атрибута учётной записи пользователя, скрипт также вносит изменения в атрибут Department учётной записи компьютера, который по умолчанию пользователи также менять не могут. Поэтому чтобы решение работало, автор предлагает изменить стандартые настройки безопасности для объектов AD.
  3. Формат даты зависит от настроек локализации на конечной машине, поэтому с одной машины можем получить 10 ноября 2018 14:53, а с другой 11/10/18 2:53 p.m.

Для устранения этих недостатков было сделано следующее.

  1. GPO линкуется не к домену, а к OU с машинами (я разделяю пользователей и машины по разным OU и другим советую). При этом для loopback policy processing mode выставлен режим merge.
  2. Скрипт будет заносить данные только в учетную запись пользователя в атрибут Info, который пользователь может менять самостоятельно для своей учётной записи.
  3. Изменен кусок кода, генерирующий значение атрибута

Теперь скрипты выглядят так:
SaveLogonInfoToAdUserAttrib.vbs

On Error Resume Next
Set wshShell = CreateObject("WScript.Shell")
strComputerName = wshShell.ExpandEnvironmentStrings("%COMPUTERNAME%")
Set adsinfo = CreateObject("ADSystemInfo")
Set oUser = GetObject("LDAP://" & adsinfo.UserName)
strMonth = Month(Now())
If Len(strMonth) < 2 then
  strMonth = "0" & strMonth
End If
strDay = Day(Now())
If Len(strDay) < 2 then
  strDay = "0" & strDay
End If
strTime = FormatDateTime(Now(),vbLongTime)
If Len(strTime) < 8 then
  strTime = "0" & strTime
End If
strTimeStamp = Year(Now()) & "/" & strMonth & "/" & strDay & " " & strTime
oUser.put "info", strTimeStamp & " <logon>" & " @ " & strComputerName
oUser.Setinfo

SaveLogoffInfoToAdUserAttrib.vbs

On Error Resume Next
Set wshShell = CreateObject("WScript.Shell")
strComputerName = wshShell.ExpandEnvironmentStrings("%COMPUTERNAME%")
Set adsinfo = CreateObject("ADSystemInfo")
Set oUser = GetObject("LDAP://" & adsinfo.UserName)
strMonth = Month(Now())
If Len(strMonth) < 2 then
  strMonth = "0" & strMonth
End If
strDay = Day(Now())
If Len(strDay) < 2 then
  strDay = "0" & strDay
End If
strTime = FormatDateTime(Now(),vbLongTime)
If Len(strTime) < 8 then
  strTime = "0" & strTime
End If
strTimeStamp = Year(Now()) & "/" & strMonth & "/" & strDay & " " & strTime
oUser.put "info", strTimeStamp & " <logoff>" & " @ " & strComputerName
oUser.Setinfo

Кто первым найдет все отличия между логон- и логофф-скриптом, тому плюс в карму. 🙂
Также для получения наглядной информации создан такой небольшой PS-скрипт:
Get-UsersByPCsInfo.ps1

$OU = "OU=MyUsers,DC=mydomain,DC=com"
Get-ADUser -SearchBase $OU -Properties * -Filter * | Select-Object DisplayName, SamAccountName, info | Sort DisplayName | Out-GridView -Title "Информация по логонам" -Wait

Итого всё настраивается на раз-два-три:

  1. создаем GPO с нужными настройками и линкуем его к подразделению с рабочими станциями пользователей:
    Windows: узнаём, кто где залогинен
  2. идем пить чай (если AD с большим количеством пользователей, то чая нужно много 🙂
  3. запускам PS-скрипт и получаем результат:
    Windows: узнаём, кто где залогинен
    В верхней части окна есть удобный фильтр, в котором можно отбирать данные по значениям одного или нескольких полей. Клик по столбцам таблицы сортирует записи по значениям соответствующих полей.

Можно красиво «упаковать» наше решение.
Windows: узнаём, кто где залогинен
Для этого добавим ярлык для запуска скрипта специалистам техподдержки, у которого в поле «объект» будет что-то такое:
powershell.exe -NoLogo -ExecutionPolicy Bypass -File "servershareScriptsGet-UsersByPCsInfo.ps1"

Если сотрудников техподдержки много, то можно раздать ярлык с помощью GPP.

Несколько замечаний напоследок.

  • На машине, откуда запускается PS-скрипт, должен быть установлен модуль Active Directory для PowerShell (для этого достаточно добавить средства администрирования AD в компонентах Windows).
  • бОльшую часть атрибутов своей учётной записи пользователь по умолчанию редактировать не может. Учитывайте это, если решите использовать атрибут, отличный от Info.
  • Проинформируйте всех причастных коллег о том, какой атрибут будете использовать. Например, тот же Info используется для интерактивного добавления заметок к ящику пользователя в админке Exchange Server и кто-то легко может его затереть, либо опечалился, когда добавленную им информацию затрет ваш скрипт.
  • Если у вас несколько сайтов Active Directory, то делайте поправку на задержки репликации. Например, если вы хотите получить актуальную информацию о пользователях с AD-сайта A, а запускаете скрипт с машины из AD-сайта B, то можно сделать так:
    Get-ADUser -Server DCfromSiteA -SearchBase $OU -Properties * -Filter * | Select-Object DisplayName, SamAccountName, info | Sort DisplayName | Out-GridView -Title "Информация по логонам" -Wait

    DCfromSiteA — имя контроллера домена сайта A (по умолчанию командлет Get-AdUser подключается к ближайшему контроллеру домена)

Windows: узнаём, кто где залогинен

Источник картинок

Буду признателен, если вы пройдете короткий опрос ниже.

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

Чем пользуетесь?

  • bginfo, Desktop info etc. (бесплатное ПО)

  • платные аналоги bginfo

  • сделаю так, как в статье

  • не актуально, т.к. использую VDI/RDS etc.

  • пока не использую ничего, но задумываюсь

  • мне не нужно собирать такие данные

  • другое (поделитесь в комментариях)

Проголосовали 112 пользователей. Воздержались 39 пользователей.

Источник: habr.com