1

Тема: VBS: заполнение "Описание" для компа в АД именем залогиненного юзера

Доброго времени суток.
Стоит такая задача: в поле "описание" для компьютеров в домене прописать имя залогиненного на данном компьютере пользователя в виде "Фамилия Имя Отчество".
Нашел скрипт, который пишет в виде "domain\username".
Есть идеи как писать туда именно ФИО данного пользователя?

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

Взято http://shss.wordpress.com/2010/01/21/se … ect-in-ad/.

2

Re: VBS: заполнение "Описание" для компа в АД именем залогиненного юзера

В пределах домена (пакетник)

echo off
setlocal ENABLEDELAYEDEXPANSION
set domain=
set user=
for /f "delims=\ " %%i in ('net view ^| find "\\"') do (
    set comp=%%~i
    ping -n 1 -w 10 !comp! > nul 2>&1 && (
        for /f "tokens=2,3 delims==\" %%d in ('wmic /failfast:on /output:STDOUT /node:"!comp!" ComputerSystem get username /format:value 2^> nul ^| find "="') do (
            set user=%%~e
            set domain=%%~d
            set domain=!domain:~0!
            if /i "%userdomain%"=="!domain!" (
                set user=!user:~0,-1!
                net user "!user!" /domain > nul 2>&1 && (
                    for /f "delims=" %%u in ('dsquery user -samid "!user!" -scope subtree -o dn ^| dsget user -fn -mi -ln -display -L 2^> nul ^| find ": "') do (
                            set name=%%~u
                            set name=set !name:: ==!
                            !name!
                        )
                        set fullname=!fn! !mi! !ln!
                        set fullname=!fullname:"='!
                        set display=!display:"='!
                        dsquery computer domainroot -name "!comp!" -scope subtree -o dn | dsmod computer -desc "!fullname! (!display!)" 2> nul && echo !comp! - !fullname! (!display!^)
                    )
                )
            )
        )
    )
Я конечно далек от мысли... (с)

3 (изменено: holydiver, 2010-12-02 13:17:22)

Re: VBS: заполнение "Описание" для компа в АД именем залогиненного юзера

Спасибо, работает
Вот только... Нельзя ли хоть немного объяснить что тут происходит? С пакетными файлами дело имел, но, видимо, не до такой степени...

Мне бы как-то исключить сервера. А еще лучше - указать OU, в которой это все делать. Тут ведь просто в net view все смотрит.

4

Re: VBS: заполнение "Описание" для компа в АД именем залогиненного юзера

исключаем контроллеры автоматом + список внесенный в exclude через пробелы или запятые или точку с запятой
(с подразделением не вкурил, надо компьютеры только из определенных подразделений АД ?)

echo off
setlocal ENABLEDELAYEDEXPANSION
set exclude=proxy;pavel igor,ws013
for %%i in (%exclude%) do (
    set "regexclude=!regexclude! \<%%i\>"
    )
set domain=
set user=
for /f "delims=\ " %%i in ('net view ^| find "\\"') do (
    set comp=%%~i
    ping -n 1 -w 10 !comp! > nul 2>&1 && dsquery server -o rdn | find /v /i "!comp!" > nul && echo !comp! | findstr /i /v /r "%regexclude%" > nul && (
        for /f "tokens=2,3 delims==\" %%d in ('wmic /failfast:on /output:STDOUT /node:"!comp!" ComputerSystem get username /format:value 2^> nul ^| find "="') do (
            set user=%%~e
            set domain=%%~d
            set domain=!domain:~0!
            if /i "%userdomain%"=="!domain!" (
                set user=!user:~0,-1!
                net user "!user!" /domain > nul 2>&1 && (
                    for /f "delims=" %%u in ('dsquery user -samid "!user!" -scope subtree -o dn ^| dsget user -fn -mi -ln -display -L 2^> nul ^| find ": "') do (
                            set name=%%~u
                            set name=set !name:: ==!
                            !name!
                        )
                        set fullname=!fn! !mi! !ln!
                        set fullname=!fullname:"='!
                        set display=!display:"='!
                        dsquery computer domainroot -name "!comp!" -scope subtree -o dn | dsmod computer -desc "!fullname! (!display!)" 2> nul && echo !comp! - !fullname! (!display!^)
                    )
                )
            )
        )
    )
Я конечно далек от мысли... (с)

5

Re: VBS: заполнение "Описание" для компа в АД именем залогиненного юзера

с ОУ вкурил, делается и так и через свободный запрос с фильтром
но некоторая проблема с вложенностью, как указать, что этот не рекурсивно а этот рекурсивно, тупо писать подряд не хочется
скрипт усложнится если продумать то строк на 5-10 всего и все ОУ указывать можно будет не задумываясь о нахождении его

просто счас лениво, может завтра

Я конечно далек от мысли... (с)

6

Re: VBS: заполнение "Описание" для компа в АД именем залогиненного юзера

Окей, спасибо большое!=)

7

Re: VBS: заполнение "Описание" для компа в АД именем залогиненного юзера

А можно узнать как это запускать!!!

8

Re: VBS: заполнение "Описание" для компа в АД именем залогиненного юзера

это обычный "батник"

Я конечно далек от мысли... (с)

9

Re: VBS: заполнение "Описание" для компа в АД именем залогиненного юзера

После запуска он "висит" секунд 10 и закрывается.
А результата я не вижу..., описание ПК пустое.

10

Re: VBS: заполнение "Описание" для компа в АД именем залогиненного юзера

это для описаний ПК в Актив директори, а не тот что комментарий ланмансервера

Я конечно далек от мысли... (с)

11

Re: VBS: заполнение "Описание" для компа в АД именем залогиненного юзера

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

остановка
обозреватель
сетевой вход
сервер

запуск
сервер
сетевой вход
обозреватель

могут быть еще и ДФС и служба развертывания виндуз

Я конечно далек от мысли... (с)

12

Re: VBS: заполнение "Описание" для компа в АД именем залогиненного юзера

Пардон, что снова поднимаю тему.
Начальнику необходимо, чтобы скрипт запускался от каждого юзера, и не перебирал все компы, а записывал только в свой. То есть юзер логинится, выполняется данный скрипт, который в описание компа в АД, на котором залогинился юзер, запишет его ФИО. Такие дела...

13

Re: VBS: заполнение "Описание" для компа в АД именем залогиненного юзера

убить начальника

Я конечно далек от мысли... (с)

14 (изменено: jite, 2010-12-09 11:13:26)

Re: VBS: заполнение "Описание" для компа в АД именем залогиненного юзера

Upd. Ну раз отвечают, значит это только одному мне вопрос непонятен...

15

Re: VBS: заполнение "Описание" для компа в АД именем залогиненного юзера

holydiver пишет:

... необходимо, чтобы скрипт запускался от каждого юзера, и не перебирал все компы, а записывал только в свой. То есть юзер логинится, выполняется данный скрипт, который в описание компа в АД, на котором залогинился юзер, запишет его ФИО...

Поищите на форуме темы по ключу "проксирование".

16 (изменено: holydiver, 2010-12-09 12:33:57)

Re: VBS: заполнение "Описание" для компа в АД именем залогиненного юзера

smaharbA пишет:

убить начальника

Хороший совет
Можно ли как-то твой пакетник переделать, чтобы он не пробегался по всем компам, а делал только у того компа, на котором залогинен юзер?

jite пишет:

Upd. Ну раз отвечают, значит это только одному мне вопрос непонятен...

Собственно, для ясности все же подробно опишу свою задачу.

В оснастке "АД - пользователи и компьютеры" есть контейнер Computers, где лежат все записи компов домена. У каждой этой записи есть поле "Описание". Необходимо сделать так, чтобы когда пользователь логинился на какой-то машине - отрабатывался скрипт, который делает следующее: в "Описание" компьютера в АД, на котором залогинился пользователь записать ФИО этого пользователя.

Dmitrii пишет:

Поищите на форуме темы по ключу "проксирование".

Поискал. Но не очень понял как это применимо касательно решения моей задачи...

17

Re: VBS: заполнение "Описание" для компа в АД именем залогиненного юзера

holydiver пишет:

Можно ли как-то твой пакетник переделать...

Можно
Спасибо, переделал все как надо! Сделал чтобы при логоне пользователя этот скрипт запускался от учетки, имеющей доступ писать в этой описание компов в АД, все работает

18

Re: VBS: заполнение "Описание" для компа в АД именем залогиненного юзера

holydiver пишет:

... Сделал чтобы при логоне пользователя этот скрипт запускался от учетки, имеющей доступ писать в этой описание компов в АД...

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

19

Re: VBS: заполнение "Описание" для компа в АД именем залогиненного юзера

Мм.. Вот теперь понял. Спасибо!
А все равно отказались от этой идеи. Запускается скрипт от компа.

20

Re: VBS: заполнение "Описание" для компа в АД именем залогиненного юзера

парни объясните на пальцах, как это работает

21

Re: VBS: заполнение "Описание" для компа в АД именем залогиненного юзера

BANDI-OGA, объясните на пальцах, что «это»?

22

Re: VBS: заполнение "Описание" для компа в АД именем залогиненного юзера

alexii пишет:

BANDI-OGA, объясните на пальцах, что «это»?

ну как запускать, в групповую политику совать и накатывать на каждого пользака или это от одного пользователя отрабатывается

23

Re: VBS: заполнение "Описание" для компа в АД именем залогиненного юзера

Что имено мне здесь надо исправить под себя, set domain= set user= это я добавил и все?

24

Re: VBS: заполнение "Описание" для компа в АД именем залогиненного юзера

Попробуйте за разъяснениями написать коллеге smaharbA в личку, сюда он заходит достаточно спорадически.

25

Re: VBS: заполнение "Описание" для компа в АД именем залогиненного юзера

Что то smaharbA не отвечает, парни подскажите если кто знает про этот скрипт?

26

Re: VBS: заполнение "Описание" для компа в АД именем залогиненного юзера

А теперь обратная задача... Заполнить поле "Описание" у пользователя в АД - именем компа, на котором он залогинен.
Написал такой вот незамысловатый скрипт:

Const ADS_PROPERTY_UPDATE = 2 

Function Environ(VarName)
    Dim wss, env
    Set wss = CreateObject("WScript.Shell")
    Set env = wss.environment("process")
    Environ = env(VarName)
    If Environ = "" Then
        Set env = wss.environment("system")
        Environ = env(VarName)
    End If
End Function

Set objWshShell =  WScript.CreateObject("WScript.Shell")
strEnv      =  Environ("COMPUTERNAME")

On Error Resume Next

set objParent = GetObject("LDAP://ou=Уволенные,ou=Пользователи,ou=Новосибирск_nov,ou=Площадки,dc=domain,dc=local")
objParent.Filter = Array("user")
for each objUser in objParent

    objUser.PutEx ADS_PROPERTY_UPDATE, "description", Array(strEnv)

    objUser.SetInfo
    On Error GoTo 0
next

Вот только проблема. Пользователь в своей учетке в АД не может править поле "Описание". Да и вообще - скрипт сей пробегается по всей OU и редактирует все учетки одним именем компа, от которого запущен.
А надо чтобы он запускался от юзера и только свою учетку в АД редактировал этим описанием...

Смотрю в сторону cmd и dsquery, но что-то пока нет мыслей по реализации.

27

Re: VBS: заполнение "Описание" для компа в АД именем залогиненного юзера

holydiver пишет:

... Пользователь в своей учетке в АД не может править поле "Описание"...

Вариант 1 Вы уже применяли для заполнения поля описания объекта-компьютера: "Сделал чтобы при логоне пользователя этот скрипт запускался от учетки, имеющей доступ писать в этой описание компов в АД".
Вариант 2 предлагал Вам я - это "проксирование".
Вариант 3 - наблюдение за появлением события о регистрации сеанса пользователя в журнале событий контроллера на стороне самого контроллера и внесение соответствующих изменений в AD (то же самое и при завершении сеанса).

holydiver пишет:

... скрипт сей пробегается по всей OU и редактирует все учетки одним именем компа, от которого запущен...

Вы сами позволили ему это делать:

for each objUser in objParent
'...
next
holydiver пишет:

... надо чтобы он запускался от юзера и только свою учетку в АД редактировал этим описанием...

Ну и выполняйте привязку не к объекту-подразделению, а к объекту-пользователю.

28

Re: VBS: заполнение "Описание" для компа в АД именем залогиненного юзера

с cmd все просто ))

dsquery user -name %username% | dsmod user -desc "%computername%"

вот только нет прав у юзера редактировать этот пункт...=( как сие обойти?

29

Re: VBS: заполнение "Описание" для компа в АД именем залогиненного юзера

Dmitrii, я так ничего с проксированием и не понял

А вариант 1 не подошел тем, что в vbs-скрипте не всегда подхватывается пароль.. Поэтому он запускатся-таки от компа.

30

Re: VBS: заполнение "Описание" для компа в АД именем залогиненного юзера

Теперь иная задача...
Раз уж в "Описание" юзер ничего не может добавить, то имя компа надо писать в поле "Комната", причем в таком формате: номер_комнаты (имя_компьютера).

Имя компов у нас в формате com123ws01
Где com - 3-хбуквенное имя площадки
123 - номер комнаты
ws - вёркстэйшн
01 - номер розетки.

Собственно, разобрать переменную среды %computername% и выделить номер комнаты не сложно: %COMPUTERNAME:~3,-4%

Вот только как это в vbs-скрипте сделать?

Function Environ(VarName)
    Dim wss, env
    Set wss = CreateObject("WScript.Shell")
    Set env = wss.environment("process")
    Environ = env(VarName)
    If Environ = "" Then
        Set env = wss.environment("system")
        Environ = env(VarName)
    End If
End Function

asdf = Environ("COMPUTERNAME:~3,-4")
msgbox(asdf)

Set WSHShell = WScript.CreateObject("WScript.Shell")
usernamevar = WshShell.ExpandEnvironmentStrings("%COMPUTERNAME:~3,-4%")
msgbox(usernamevar)

Вот только оба варианта не работают. Как мне регулярные выражения для переменных среды в vbs-скрипте использовать?

31

Re: VBS: заполнение "Описание" для компа в АД именем залогиненного юзера

Блин... Почему я нахожу ответ сразу после того как отпишусь на форуме?..

dsquery user -name %username% | dsmod user -office "%computername:~3,-4% (%competername%)

32 (изменено: Dmitrii, 2011-01-27 18:05:53)

Re: VBS: заполнение "Описание" для компа в АД именем залогиненного юзера

Судя по предыдущему сообщению, задача решена.
Осталось лишь разобраться с "проксированием" (ну, например, на будущее).

1. Создаём папку общего доступа, с правами для рядовых пользователей только на запись (значение маски либо &H100116, либо &H40000000).

2. Пишем "LogOn"-сценарий, который будет создавать в этой папке некий сигнальный файл. Например, это может быть пустой текстовый файл, имя которого состоит из пары: имя станции + имя пользователя.
И включаем этот сценарий в нужным образом в групповую политику.

3. Пишем сценарий для регистрации временной или постоянной (с моей точки зрения, временная - практичнее) подписки на событие появления в папке общего доступа сигнальных файлов от пользователей.
И запускаем этот сценарий с нужными полномочиями.
Сценарий, получив сигнал о наступлении события, делает следующее:
- выполняет привязку к соответствующему объекту-пользователю в AD;
- вносит изменения в поле описания этого объекта;
- удаляет сигнальный файл.

Таким образом, пользователи, имея лишь свои базовые права, могут инициировать процесс внесения изменений в AD.

Понятно объяснил?

33 (изменено: holydiver, 2011-02-02 09:47:26)

Re: VBS: заполнение "Описание" для компа в АД именем залогиненного юзера

Так, но идея, вроде бы, ясна.
А как реализовать сей сценарий (пункт 3), не совсем понятно.

ЗЫ, кстати, по решению что я выше привел - все работает. Вот только одно но... Нужна проверка, если там уже имеются такие данные, то ничего не делать. Я сделал так:

for /F "tokens=2 delims=: " %%A in ('dsquery user -name %username% ^| dsget user -office -L ^| find "%computername:~3,-4%"') do set proverka=%%A

echo "%proverka% == %computername:~3,-4%"

if %proverka% == %computername:~3,-4% ( 
    goto exit 
    ) else (
    goto dsq
    )
    
:dsq
dsquery user -name %username% | dsmod user -office "%computername:~3,-4% ( %computername% )"
    
:exit
echo exit
pause

Проблема в том, что первоначально в том поле ничего нет, поэтому переменной среды присваивается пустое значение, а его ни с чем сравнивать нельзя...

34

Re: VBS: заполнение "Описание" для компа в АД именем залогиненного юзера

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

Пустое? Можно:

if defined proverka …

35

Re: VBS: заполнение "Описание" для компа в АД именем залогиненного юзера

Вот спасибоньки
Все получилось!

36

Re: VBS: заполнение "Описание" для компа в АД именем залогиненного юзера

holydiver пишет:

... идея, вроде бы, ясна. А как реализовать сей сценарий (пункт 3), не совсем понятно...

Поищите на форуме темы по ключу __InstanceCreationEvent