Инвентаризация малой кровью

Однажды потребовалось провести «инвентаризацию», то есть узнать за каким компьютером, какой пользователь сидит.

Вариант пройти по рабочим местам посмотреть, поспрашивать, был отброшен, как еретический.
Так как все пользователи заведены в Службе каталогов Active Directory, так же, как и рабочие места, родилась идея выдрать всю необходимую информацию из AD. Можно, конечно было обратиться к администратору домена и спросить все данные у него, но мы не ищем легких путей.

Итак, для инвентаризации Нужно:
  • Сетевое имя компьютера.(Все компьтеры под Win разных версий)
  • Мак адрес этого компьютера.(Все компьютеры находятся в одной подсети 255.255.0.0)
  • ФИО пользователя, который за этим компом закреплен.


И самое главное условие — это крайнее нежелание ставить на комп каких-либо сторонних приложений, писать приложение на «правильных» языках, тоже было лень. Поэтому для реализации был выбран VBS, так как в нем есть все, что необходимо и ничего дополнительно ставить не нужно и среда для него самая легковесная — notepad.exe.
С сетевыми именами все просто, они есть в службе каталогов. Пример работы с AD из VBS нагуглился довольно быстро. Для получения списка атрибутов объектов использовался скрипт написанный
товарищем Andrew J. Healey listAllProperties
Так что получить имена компьютеров получилось таким нехитрым скриптом.
	set cn=CreateObject("ADODB.Connection")
	set cmd=CreateObject("ADODB.Command")
	cn.Provider="ADsDSOObject"
	cn.Open "Active Directory Provider"
	set cmd.ActiveConnection=cn
используя SQL диалект запросов к Active directory выбираем все обекты класса "Computer"
	cmd.CommandText="SELECT * FROM 'LDAP://DC=***,DC=ru' WHERE objectClass='Computer'"
	set objRecordSet=cmd.Execute
	on error resume next
	do while Not objRecordSet.Eof
	set objComputer=GetObject(objRecordSet("adspath"))
	'путем бесчеловечных экспериментов было выяснено, что если путь содержит данную фразу 
	'то это демонтированное оборудование, или уволенный работник
	if(inSTR(1,objComputer.distinguishedName,"OU=Garbage",vbTextCompare) = 0)then 
		wscript.echo  objComputer.CN 'В данном поле и хранилось заветное сетевое имя
	end if
	objRecordSet.MoveNext
Loop


Далее, нужно получить мак адрес этих компов. Тут все просто, при помощи стандартной утилиты «nbtstat» с параметром "-a" можно получить искомое(есть конечно еще вариант с arp -a, но работает не всегда).
	set oShell=Wscript.CreateObject("wscript.shell")
	set re=new regexp
	'Регулярка для поиска MAC адреса
	re.Pattern = "[0-9A-F]{2}-[0-9A-F]{2}-[0-9A-F]{2}-[0-9A-F]{2}-[0-9A-F]{2}-[0-9A-F]{2}"
	' В данном случае ComputerNetworkName имя компа которое мы взяли из AD
	set oExec=oShell.Exec("nbtstat -a" & ComputerNetworkName) 
	for each obj in re.execute(oExec.StdOut.ReadAll)
		GetData=obj.value
	next

Теперь возникает вопрос: «А где собсно взять список пользователей зарегистрированных на данном компьютере?». Путем непродолжительного гугления было найдено множество способов, которые сводились к удаленному выполнению wmi скрипта. Этот путь мне не подходил, так как в домене запрещено удаленное выполнение скриптов. И тут вспомнилось, что в Windows по умолчанию доступны для чтения по сети, 2 ветки реестра, а именно «HKEY_USERS» и «HKEY_LOCAL_MACHINE».
Значит, получить SID для зарегистрированных пользователей можно получить при помощи утилиты «reg» и в этом нам поможет код, который мы использовали для получения MAC адреса, все, что в нем нужно изменить так это шаблон для регулярки, и текст команды.
	set oShell=Wscript.CreateObject("wscript.shell")
	set re=new regexp
	'Регулярка для поиска SID в выводе команды reg query
	re.Pattern = "S-\d+-\d+-\d+-\d+-\d+-\d+-\d+"
	' В данном случае ComputerNetworkName имя компа которое мы взяли из AD

	set oExec=oShell.Exec("reg query \\" & iComputerNetworkName&"\HKEY_USERS") 
	for each obj in re.execute(oExec.StdOut.ReadAll)
		GetData=obj.value
	next

Ну, хорошо сиды у нас есть, но они на ФИО не похожи, совсем. Чтобы получить ФИО опять придется обращаться к AD.
У каждого объекта в AD есть поле «objectSID», а значит выбрать инфу о пользователе можно, поэтому самому сиду. Для этого возьмем код, который мы использовали для получения списка компьютеров, и изменим в нем запрос в поле «cmd.commandtext»:

	dim cn,cmd,objRecordSet
	set cn=CreateOBject("ADODB.Connection")
	set cmd=CreateObject("ADODB.Command")
	cn.Provider="ADsDSOObject"
	cn.Open "Active Directory Provider"
	set cmd.ActiveConnection=cn
	' objSid это сиды которые мы получили из реестра.
	cmd.CommandText="SELECT * FROM 'LDAP://DC=***,DC=ru' where objectClass='User' and objectSid='"& objSid &"' " 
	set objRecordSet=cmd.Execute
	'Вдруг пользователя с таким сидом нет
	if( not objRecordSet.Eof) then
		set objUser=GetObject(objRecordSet("adspath"))
		if(inSTR(1,objUser.distinguishedName,"OU=Garbage",vbTextCompare) = 0)then
			' Если он всетаки есть, и еще и не в мусоре, выводим его данные.
			Wscript.Echo objUser.FirstName &" "& objUser.LastName &" "& objUser.Patronim
		end if
	end if

Ну, вот и все нужные данные получены, причем, даже если они изменятся в дальнейшем получить их, не будет проблемой (если конечно служба каталогов не будет реорганизована). И что самое главное не пришлось бегать, всему предприятию в поисках компов и пользователей.
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама

Комментарии 11

    +1
    Это не инвентаризация в её подлинном смысле. А что у вас имеется ввиду под понятием «зарегистрированный пользователь»? Кто сейчас вошел в систему или кто вообще хоть раз заходил? Ну и как вариант изначально ФИО пользователя машины можно забивать в поле описания компьютера. Даже скриптом в момент входа в систему.
      0
      В данном случае «Зарегестрированный пользователь» это пользователь закрепленный за данным рабочим местом(в AD). На счет скриптов, я не являюсь администратором домена и не могу ставить свои скрипты на рабочие места(А администраторам это не нужно, ибо задача одноразовая). Помимо ФИО может понадобиться еще и табельный номер, телефон, еще что-нибудь. В службе какталогов эта информация есть, а добавлять ее в описание аккаутна, обычно не нужно. А по поводу названия, действительно неудачно выбрал.
        0
        Есть тут минус, запрос к реестру выдаст всех заходивших на компьютер пользователей. Это и коллега, который один раз залогинился, и кто-нибудь из службы поддержки, настраивавший компьютер под своей учетной записью.
        По поводу WMI — извлечение информации из WMI не подразумевает запуска какого либо скрипта на машине, должна лишь быть запущена служба и не закрыты брандмауэром порты.
        Попробуйте в Powershell выполнить:
        gwmi -comp <имя_компьютера> -class win32_share.
        Если отработает — то думаю найденные вами решения с запросами к WMI можно было использовать.
          0
          Нет к сожалению не работает, говорит, что отказано в доступе.

          Get-WmiObject : Отказано в доступе. (Исключение из HRESULT: 0x80070005 (E_ACCESSDENIED)) строка:1 знак:5 + gwmi <<<< -comp ***.***.***.*** -class win32_share + CategoryInfo : NotSpecified: (:) [Get-WmiObject], UnauthorizedAccessException + FullyQualifiedErrorId : System.UnauthorizedAccessException,Microsoft.PowerShell.Commands.GetWmiObjectCommand
            0
            Вы правы, в реестре содержится запись последнего залогиневшегося пользователя. Но в данном случае мне повезло.
          0
          echo %date% %time% %computername% %username% >> \\server\share$\logon-log.txt
          Можно добавить как run-script в какое-нибудь GPO и потом уже его смотреть.
          Но вообще — желательно сразу планировать механизмы, которые бы позволяли видеть соответствие в любой момент не выполняя лишних действий. Например, использовать поле Managedby для объекта компьютера в AD.
            0
            Если бы у меня были права администратора домена, я бы возможно вообще не заморачивался, просто взял связку (пользователь-> рабочая станция) непосредственно из службы каталогов. Но я не администратор, а также в АД мне видно далеко не все. Задача была одноразовая, поэтому вводить подобный механизм ни кто не стал бы.
            0
            pstools — psloggedon.
            Показывает залогиненного на конкретный пк пользователя — распарсить вывод не проблема.
            Если это разовая задача.
              0
              Я в начале сказал, что не хотелось использовать сторонних инструментов, даже тех которые не нужно устанавливать. Софтовых вариантов множество можно найти или самому написать, но это лениво.
                0
                VBS как-то всё больше остается для аналитики excel'я или макросов для отчётов в word'e…
                Что-то серьёзно-системное на нём писать при наличии powershell'а уже смысла нет, тем более, что почти всё уже написано до нас.
                Но если Вы хотели что-то изучить для себя, и показать статью для таких же начинающих — это позитив, и я рад, что Вы это сделали. Успехов Вам.
                0
                К сожалению psloggedon требует прав администратора(прав администратора у меня нет), для получения профиля текущего пользователя на удаленном компьютере.
                Судя по описанию на сайте, она берет данные из HKEY_USERS.

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

              Самое читаемое