Скрипт для записи в атрибут Description объекта-компьютера в AD имени текущего «залогоненного» пользователя

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

  1. подойти к пользователю и посмотреть в свойствах «Моего компьютера» имя этого компьютера ;)
  2. узнать имя компьютера у пользователя
  3. выполнить опрос всех компьютеров в организации на предмет имени текущего пользователя и найти среди этих имен нужного нам пользователя, а, значит, и проблемный компьютер.
  4. заглянуть в некую БД, в которой хранится информация о том, какой компьютер был установлен на рабочем месте данного пользователя.

 Понятно, что первый вариант мы не рассматриваем, как ущербный. Второй вариант вполне удобоварим, если мы сможем упростить задачу поиска имени компьютера для конечного пользователя. Это реализуемо, но мы не будем сейчас останавливаться на этом вопросе. К тому же в идеальном случае нам бы хотелось, зная только имя пользователя и не задавая ему лишних вопросов, иметь возможность узнать имя компьютера, за которым он работает. Третий вариант всем хорош, за исключением того, что задача опроса всех компьютеров в организации занимает недопустимо много времени. Четвертый вариант успешно решает поставленную задачу, но порождает другую – кто (и каким образом) будет создавать и обновлять эту базу данных? Можно, конечно, вручную поддерживать в актуальном состоянии табличку в Excel, но «это же не наши методы» ;), хочется автоматизации. Если в вашей организации уже используется AD, то задача уже частично решена: у нас есть база данных, содержащая имена пользователей и компьютеров. Наша задача сводится к созданию связей компьютер-пользователь. Для этого можно, например, в один из атрибутов объекта компьютер записывать имя «залогоненого» на этом компьютере пользователя. В качестве такового атрибута я решил использовать атрибут Description (Описание). Этот атрибут пуст от рождения, может содержать произвольный тексты и по дефолту отображается в оснастке AD&С (dsa.msc), что позволит нам легко находить нужный нам компьютер по имени пользователя.

 Записывать имя пользователя в атрибут AD можно, как при помощи логон скрипта, так и при помощи скрипта, выполняющего опрос доступных компьютеров единовременно. У каждого из этих методов имеются свои плюсы и минусы. Меня вполне устроил второй вариант (т.к. в моем случае пользователи крайне редко меняют рабочий компьютер, а, значит, для отслеживания изменения в связке «компьютер-пользователь» скрипт опроса можно будет запускать также не часто. Кроме того, второй вариант позволяет одним разом прописать в AD информации по всем доступным рабочим станциям.)

 И так, вот, собственно, сам скрипт:

Option Explicit
Dim rootDSE,strDomainDN,objConnection
Dim strSubContainer,objCommand,objRecordSet
Dim strMsg, arrDescription, strAccountProp, objComputer, strLoggedOnUser
'определяем константы
'символ-разделитель, используемый для формирования строки отчета
Const SPLITER = ","
'констатны, определяющие глубину поиска
Const ADS_SCOPE_SUBTREE = 2
Const ADS_SCOPE_ONELEVEL = 1
'константа, выделяющая бит Enable|Disable из мультибитового атрибута userAccountControl
Const ADS_UF_ACCOUNTDISABLE = 2
'зададим контейнер AD, начиная с которого будем осуществлять поиск
strSubContainer="OU=WorkStations,OU=ORG,"
'получим DN домена
Set rootDSE = GetObject("LDAP://rootDSE")
strDomainDN = rootDSE.Get("defaultNamingContext")
'Выполняем подготовку обращения к AD при помощи ADODB
Set objConnection = CreateObject("ADODB.Connection")
Set objCommand =   CreateObject("ADODB.Command")
objConnection.Provider = "ADsDSOObject"
objConnection.Open "Active Directory Provider"
Set objCommand.ActiveConnection = objConnection
'формируем SELECT-запрос к AD
objCommand.CommandText = "Select Name, " &_
        "operatingSystem, operatingSystemServicePack, Description, userAccountControl, distinguishedName " &_
        "from 'LDAP://"&strSubContainer&strDomainDN&"' " &_
        "Where objectClass='computer'"
'определим максимальное количество объектов, возвращаемых в результирующем наборе записей
objCommand.Properties("Page Size") = 1000
'будем производить поиск по всему поддереву, начиная с заданного каталога
objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE 'ADS_SCOPE_ONELEVEL 'ADS_SCOPE_SUBTREE
'выполняем сформированный запрос, результатом которого является набор записей objRecordSet
Set objRecordSet = objCommand.Execute
If objRecordSet.RecordCount<1 Then
    WScript.Echo "No computer accounts found in "&strContainer&strDomainDN
    WScript.Quit
End If
objRecordSet.MoveFirst
Do Until objRecordSet.EOF
	''Выбираем только компьютеры, у которых Account установлен в Enabled
	''If ((InStr(objRecordSet.Fields("operatingSystem"),"XP")>0) And (InStr(objRecordSet.Fields("operatingSystemServicePack"),"2")>0)) Then
	If (objRecordSet.Fields("userAccountControl").Value And ADS_UF_ACCOUNTDISABLE)=0 Then
		'формируем строку отчета
    	strMsg = objRecordSet.Fields("Name").Value & _
    	SPLITER & objRecordSet.Fields("operatingSystem").Value & _
    	SPLITER & strAccountProp
    	arrDescription = objRecordSet.Fields("Description").Value
    	If Not IsNull (arrDescription) Then
    		strMsg = strMsg & SPLITER & arrDescription(0)
    	End If
    	WScript.Echo strMsg
    	'Вызываем функцию, возвращающую имя залогоненного пользователя на компьютере,
    	'имя компьютера передается в функцию в качестве параметра
    	strLoggedOnUser = fnGetUserName (objRecordSet.Fields("Name").Value)
    	WScript.Echo "LoggedonUser :" & strLoggedOnUser
    	'если имя залогонненого пользователя не пусто...
    	If (Not IsEmpty(strLoggedOnUser)) And (Not IsNull (strLoggedOnUser)) Then
    		'...записываем его в атрибут Description
			Set objComputer = GetObject("LDAP://"&objRecordSet.Fields("distinguishedName").Value)
    		objComputer.Put "Description" , strLoggedOnUser
			objComputer.SetInfo
    	End If
    End If
    objRecordSet.MoveNext
Loop
'
'Эта функция опрашивает компьютер, чье имя передано ей в качестве параметра и
'возвращает имя залогоненного на опрашиваемом компьютере пользователя
Function fnGetUserName (strComputer)
On Error Resume Next
Dim objWMIService, colItems, objItem
Const wbemFlagReturnImmediately = &h10
Const wbemFlagForwardOnly = &h20

   Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\CIMV2")
   Set colItems = objWMIService.ExecQuery("SELECT * FROM Win32_ComputerSystem", "WQL", _
                                          wbemFlagReturnImmediately + wbemFlagForwardOnly)

   For Each objItem In colItems
      fnGetUserName = objItem.UserName
   Next
On Error GoTo 0
End Function

Пояснения к скрипту:

Для поиска информации в AD используем ADODB (см. Searching with ActiveX Data Objects (ADO)), что позволяет обращаться к AD, при помощи SQL-подобных запросов.

objCommand.CommandText = "Select Name, " &_
        "operatingSystem, operatingSystemServicePack, Description, userAccountControl, distinguishedName " &_
        "from 'LDAP://"&strSubContainer&strDomainDN&"' " &_
        "Where objectClass='computer'" 

Скрипт обрабатывает все компьютеры, найденные в поддереве, корнем которого является узел, заданный в переменной strSubContainer. Обратите внимание, что эта переменная должна содержать либо пустую строку (тогда будут обработаны все объекты-компьютеры в домене), либо часть DN узла (без имени домена), заканчивающуюся запятой. Так, например, если мы хотим выполнить поиск компьютеров в поддереве, корнем которого является OU “OU=Sys,DC=domain,DC=local”, то переменной strSubContainer нужно присвоить значение strSubContainer “OU=Sys, ” (не забудьте про последний символ – запятую)

 Запускать скрипт лучше с правами доменного администратора, т.к. эта группа безопасности обладает достаточными правами, как для работы функции fnGetUserName (для успешного функционирования которой требуются права лок.админа на целевом компьютере), так и для изменения атрибута Description объекта-компьютер в AD.

22 Comments

  1. Pingback: Поиск компьютера в AD по содержимому атрибута Description с последующей передачей в окно «Предложение удаленной помощи» имени найденного компью

  2. Pingback: Скрипт для записи в атрибут Description объекта-компьютера в AD имени текущего «залогоненного» пользователя. Дубль два. « ShS's Blog

  3. спасибо, но к сожалению это работает только от админа( не подскажите как дать разрешение пользователю писать в АД свойство “описание”?

  4. прошу прощения за невнимательность, про делегировании я прочитал. у меня просто компы по разным оу раскиданы, от этого другой скрипт пляшет( всему домену что ли делегировать?

    • Как вам будет угодно. Всему домену – оно, конечно, проще, но я бы так не делал (в этом случае делегирование будет распространняться на DC и сервера). Я бы создал OU, в которое перенес бы всю структуру ваших OU, содержащих целевые объекты, на которые вы будете делегировать полномочия. И выполнял бы делегирование на уровне этого, вновь созданного, OU.

  5. спасибо за скрипт, только он насколько я понял пишет имена в формате domain\user, можно какнибудь сделать чтобы он писал fullname?

    • Собственно, проблемы то нет, есть обычная задачка, которая вполне успешно решается скриптами. Не вижу смысла в использовании еще одной БД. У нас же и так уже имеется БД (AD), которая содержит большую часть информации. Нужно только дописать в нее недостающую часть информации и можно пользовать.

  6. Спасибо за скрипт, только почему стартует через раз? Три раза запускал копированием в ActiveRoles Management Shell for Active Directory x64, на четвертый запускается….

  7. могли бы и указать через что запускать ваш скрипт. Powershell ISE выдает на каждую строку по десятку ошибок. то же самое выдает и activeroles management shell. если вы намеренно исказили скрипт с целью “научить” неграмотных то могли хотя бы указать это.

  8. к сожалению листинг выполнения скрипта до 12 января предоставить не смогу, но и сохранение в .vbs файл с последующим его выполнением тоже не дает нужного эффекта, если не ошибаюсь выдает ошибку о проблеме уже в 6 строке. сами попробуйте скопировать с браузера ваш скрипт сохранить его в vbs и запустить. С наступающим вас.

Leave a Reply

Your email address will not be published. Required fields are marked *

Notify me of followup comments via e-mail. You can also subscribe without commenting.