Как вычислить имя компьютера пользователя в Active Directory

ad logoДобрый день! Уважаемые читатели и гости одного из крупнейших IT блогов в России Pyatilistnik.org. В прошлый раз мы с вами производили поиск неактивных пользователей в домене. Сегодня мы сделаем еще одну полезную вещь для нашего AD, а именно научимся автоматически определять DNS-имя компьютера на котором локально залогинен пользователь и заносить эту информацию в атрибут Active Directory у пользовательской учетной записи.

Постановка задачи

В компаниях, где есть техническая поддержка пользователей, ее инженеры очень часто подключаются удаленно к компьютерам сотрудников для устранения всевозможных проблем. Чаще всего используются программы TeamViewer, встроенный помощник Windows или Dameware. Но для того, чтобы подключиться вам необходимо знать имя компьютера. Понятно, что можно каждый раз просить пользователя посмотреть его либо в окне системы или же на рабочем столе, если у вас выводится информация с помощью BGinfo. Но проще и правильнее всегда эту информацию иметь в базе Active Directory.

Поэтому мы сделаем так, что при локальном входе в компьютер, информация, о его DNS-имени будет автоматически записана в нужное нам поле. Это удобно и можно легко эту информацию выдергивать в любую программу, которая умеет работать с Active Directory, например SCCM.

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

Реализация задачи

Делать мы все будет с помощью вот такого простенького скрипта.

Set WshNetwork = WScript.CreateObject("WScript.Network")

Set objSysInfo = CreateObject("ADSystemInfo")

strUserDN = objSysInfo.UserName

Set objUser = GetObject("LDAP://" & strUserDN)

objUser.Put "Pager", WshNetwork.ComputerName

objUser.SetInfo

Давайте с вами пробежимся по каждой из строчек кода.

  • Set WshNetwork = WScript.CreateObject("WScript.Network") - это объект VBSScript позволяет получать информацию по трем свойствам имя компьютера ComputerName, имя пользователя UserNam, имя домена UserDomain и методы MapNetworkDrive(), AddPrinterConnection(), SetDefaultPrinter(). Объект WScript.Network очень часто используется в WSH.  У созданного объекта - всего три свойства и восемь методов, но они могут оказаться очень полезными. Свойства ComputerNameUserDomain и UserName возвращают, соответственно, имя компьютера, имя домена и имя текущего пользователя. Очень удобно:
  1. для протоколирования выполнения скрипта - записывается информация о том, на каком компьютере произошло то или иное событие;
  2. для выполнения каких-либо действий только на том компьютере или только с тем пользователем, который указан в нашем списке (при помощи утилит Resource Kit можно основываться и на членстве пользователей в группах).
  3. Кроме того, можно просто отображать полученную информацию - например, на Web-странице, которая используется в качестве обоев для пользователя.
  • Set objSysInfo = CreateObject("ADSystemInfo") - создание экземпляра объекта ADSystemInfoЭто невероятно полезный объект, который может возвращать всевозможную информацию о вошедшем в систему пользователе и локальном компьютере. Единственным недостатком этого объекта является тот факт, что он может быть создан только локально: вы не можете создать экземпляр ADSystemInfo на удаленном компьютере, а затем получить информацию о пользователе, вошедшем в систему на этом компьютере.
  • strUserDN = objSysInfo.UserName - получаем значение свойства strUserDN и сохраняем его в переменной с именем strUser
  • Set objUser = GetObject("LDAP://" & strUserDN) - используем эту переменную как часть вызова GetObject, который связывает нас с учетной записью пользователя.
  • objUser.Put "Pager", WshNetwork.ComputerName - изменение атрибута с помощью метода Put. В моем случае, это атрибут пейджер
  • objUser.SetInfo - подтверждаем изменения в каталоге методом SetInfo

Вы вместо атрибута "Pager" можете подставлять любой, посмотреть атрибуты можно через редактор в Active Directory. Далее создаете текстовый документ и сохраняете его с расширением vbs.

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

Создание политики во время входа в систему

Файл со скриптом у меня готов. Открываем оснастку "Управление групповой политикой". Выбираем нужное организационное подразделение к которому мы будем применять политику, в моем случае, это контейнер "Users", поэтому политику я буду применять на самый корень домена root.pyatilistnik.org. Кликаем по нему правым кликом и из контекстного меню выбираем пункт "Создать объект групповой политики в этом домене и связать его".

Создаем политику для запуска скрипта при логине пользователя

Задаем имя для нашей политики.

Узнать компьютер пользователя в AD-02
Далее нам необходимо изменить и настроить нашу политику. Для этого щелкаем по ней правым кликом и выбираем "Изменить".

Настройка GPO для запуска скрипта узнающего имя компьютера у пользователя

Переходим по пути:

Конфигурация пользователя - Политики - Конфигурация Windows - Сценарии (вход/выход из системы) - Вход в систему

У вас откроется окно с вкладкой "Сценарии" и "Сценарии PowerShell". Нас будет интересовать первая вкладка, нажимаем кнопку "Добавить".

Узнать компьютер пользователя в AD-04

Через кнопку "Обзор" вам нужно будет выбрать ваш файл vbs. Я вам советую его скопировать в сетевую папку с политикой, либо в сетевую шару, где файл будет доступен для всех.

выбор vbs скрипта для входа пользователя на компьютер

В итоге у вас должно появиться вот так, если скриптов более одного, то можно выставлять их позиции при применении. Начинаем тестирование. У меня есть тестовая учетная запись Барбоскина Геннадия, в оснастке ADUC она у меня лежит в контейнере "Users". Поле пейджер пустое.

Тестовый пользователь в оснастке ADUC

Пробуем залогиниться Геннадием на рабочей станции с Windows 10 с именем W10-CL01. После входа на компьютер, проверяем свойство "Пейджер" у данного пользователя. Как видим, все прописалось.

Узнать компьютер пользователя в AD-07

Пробуем подключиться к еще одному компьютеру с Windows 10 под именем W10-CL02. Видим, что атрибут в AD изменил свое значение на имя второго компьютера.

Узнать компьютер пользователя в AD-08

Скрипт PowerShell для записи имени системы куда был последний вход

Все то же самое можно сделать и на PowerShell, и как показала практика данный скрипт работает на более современных версиях Windows 10 и Windows 11 без проблем, да и вообще он более современный, его так же можно применять в автозагрузке с помощью групповой политики.

function Date {Get-Date -Format "yyyy.MM.dd HH:mm:ss"}

$log = "$($env:ProgramData)\Update_Pager_attribute.log"

$computername = "$((Get-WmiObject Win32_ComputerSystem).Name).$((Get-WmiObject Win32_ComputerSystem).Domain)"
$username = "$($env:USERDOMAIN)\$($env:USERNAME)"

"$(Date) Trying to set user $username Pager attribute value to $computername" | Tee-Object $log -Append

$current_user = [adsisearcher]"(&(samaccountname=$($env:USERNAME)))"

try {
$ad_user = $current_user.FindOne().GetDirectoryEntry()
$ad_user.Put("Pager",$computername)
$ad_user.SetInfo()
}
catch {
"$(Date) $($_.exception.message)" | Tee-Object $log -Append
}

еще вариант скрипта:

function Date {Get-Date -Format "yyyy.MM.dd HH:mm:ss"}

$log = "$($env:ProgramData)\Update_attributes.log"

$computername = "$((Get-WmiObject Win32_ComputerSystem).Name).$((Get-WmiObject Win32_ComputerSystem).Domain)"
$username = "$($env:USERDOMAIN)\$($env:USERNAME)"

"$(Date) Trying to set user $username Pager attribute value to $computername" | Tee-Object $log -Append

$current_user = [adsisearcher]"(&(samaccountname=$($env:USERNAME)))"

try {
$ad_user = $current_user.FindOne().GetDirectoryEntry()
$ad_user.Put("Pager",$computername)
$ad_user.SetInfo()
}
catch {
"$(Date) $($_.exception.message)" | Tee-Object $log -Append
}

###

if ($((Get-WmiObject Win32_ComputerSystem).Domain) -eq "root.pyatilistnik.org")
{
$value_to_add = "$(Date) - $($env:USERNAME)"

"$(Date) Trying to add `"$value_to_add`" string to Info attribute value for $computername" | Tee-Object $log -Append

$comp_name = "$((Get-WmiObject Win32_ComputerSystem).Name)$"
$comp_object = [adsisearcher]"(&(samaccountname=$comp_name))"
$comp = $comp_object.FindOne().GetDirectoryEntry()

# $values_current = @()
# $values_current = $comp.Properties["Info"].Value -split ";"
# $comp.Properties["Info"].Value
$value_new = $null
$value_new = "$($comp.Properties["Info"].Value);$value_to_add"

$values_new = $value_new -split ";"
if ($values_new.Length -gt 3)
{
$value_new = ($values_new | select -Last 3) -join ";"
}
# $value_new

###

try {
$comp.Put("Info", $value_new)
$comp.SetInfo()
}
catch {
"$(Date) $($_.exception.message)" | Tee-Object $log -Append
}
}

Напоминаю, что записываться будут только локальные входы. Сама реализация до безобразия проста, но надежна. Надеюсь, что кому-то данная заметка оказалась полезной, а с вами был Иван Семин, автор и создатель IT блога Pyatilistnik.org.

Оцените статью
Настройка серверов windows и linux
Добавить комментарий

  1. Дмитрий

    Может лучше IP-адрес запилить?!

  2. Иван Семин автор

    Задачи у всех разные, у заказчика была такая хотелка

  3. Сергей

    Как все оказывается просто. Очень полезный скриптик, для не замороченны.Спасибо большое!

  4. Иван Семин автор

    Да скрипты, это сила

  5. Вадим

    А что значит «только локальные входы»?

  6. Галым

    У нас в некоторых пользователях есть по два компьютера. Они заходят на эти компьютеры со одной учётной записью. Можно сделать так, чтобы оба имя компьютера отображалось в пейджере.

  7. Иван Семин автор

    Можно, взяв второе поле, например номер комнаты или создать свое в схеме AD, у меня возможно было, что-то подобное на PowerShell

  8. Иван Семин автор

    те которые совершены интеративно, без РДП, так сказать консольно

  9. Галым

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

  10. Вадим

    To Галым, примерно так:

    Set WshNetwork = WScript.CreateObject(«WScript.Network»)
    Set objSysInfo = CreateObject(«ADSystemInfo»)

    strUserDN = objSysInfo.UserName

    Set objUser = GetObject(«LDAP://» & strUserDN)

    On Error Resume Next
    Err.Clear
    Pager = objUser.Get(«Pager»)
    If Err.Number 0 Then
    Pager = «»
    Err.Clear
    End If
    On Error Goto 0

    CurrentComputer = WshNetwork.ComputerName
    If InStr(1, «;» & Pager & «;», «; & CurrentComputer & «;», vbTextCompare) = 0 Then
    objUser.Put «Pager», Pager & CurrentComputer & «;»
    objUser.SetInfo
    End If

  11. Николай

    Добрый день! А если у меня не отрабатывает скрипт, я проделал все описанное выше.

  12. Иван Семин автор

    Нужно посмотреть в логах

  13. Влад

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

  14. Роман

    КАК игнорировать к удаленному рабочему столу, например на терминальные сервера?

  15. Роман

    Подскажите пожалуста.
    У меня добавляєт терминальние сервера, как их игнорировать?

  16. Иван Семин автор

    Не совсем понимаю, что значит игнорировать?

  17. Роман

    когда пользователь откривает remoteapp то имя сервера remoteapp также записивает.
    как исправить ето?

  18. Иван Семин автор

    Куда записывает-то?

  19. Роман

    Объясню подробно.

    То есть, сначала при локальном входе пользователя записываеться его имя пк как положено. Все работает. Например «PC-04»
    Однако как только этот пользователь входит на терминальный сервер «server-22», или открывает remoteapp — строка «пейджер» перезаписываться на имя сервера терминалов, и в строке «пейджер» теперь вместо «PC-04» записано «server-22»

  20. Юрий

    В политике примените WMI фильтр (распространите только операционные системы, кроме серверных)

  21. Иван Семин автор

    А это решение, спасибо за подсказку.

  22. Dmitriy

    при запуске сценария PS ошибку выдает- Исключение при вызове «SetInfo» с «0» аргументами: «Отказано в доступе.
    если запускать под другим пользователем с правами админа домена то лог работает,
    подскажите в чем собственно проблема ?
    при запуске vbs скрипта ошибка
    Отказано в доступе
    код 80070005