<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
	<title type="html"><![CDATA[Серый форум &mdash; AD/HTA-VBS: Управление группами у/з на указанном DC]]></title>
	<link rel="self" href="https://forum.script-coding.com/extern.php?action=feed&amp;tid=8954&amp;type=atom" />
	<updated>2013-11-29T15:02:42Z</updated>
	<generator>PunBB</generator>
	<id>https://forum.script-coding.com/viewtopic.php?id=8954</id>
		<entry>
			<title type="html"><![CDATA[AD/HTA-VBS: Управление группами у/з на указанном DC]]></title>
			<link rel="alternate" href="https://forum.script-coding.com/viewtopic.php?pid=77711#p77711" />
			<content type="html"><![CDATA[<p>По долгу службы необходимо было десятки раз на дню переключаться в AD-оснастке на разные контроллеры домена для выдачи прав (групп) пользователям/машинам. </p><br /><p>Т.к. основной программке работы с пользователем известен контроллер, на котором залогинен этот пользователь, сваял небольшое HTA, которое заменяет в известной мере саму AD-оснастку: позволяет выбрать из AD группы (по маске имени) и добавить пользователя в группы на указанном сервере или удалить его из выбранных из имеющихся у него групп.</p><p>Программку вызываю из основого приложения в качестве модального диалога, но реализована его работа и в качестве отдельного приложения.</p><p><strong>Скрипт позволяет:</strong><br /></p><div class="fancy_spoiler_switcher"><div class="fancy_spoiler_switcher_header" data-lang-open="открыть спойлер" data-lang-close="скрыть спойлер"><strong>+</strong>&nbsp;открыть спойлер</div><div class="fancy_spoiler"><p>- получить группы у/з на контроллере (указанном явно либо текущем);<br /> - выбрать из полученных групп некоторые (или все) для их удаления (или выдачи другой учётной записи);<br /> - указать маску (начало имени) для выборки из AD группы - для последующего её добавления учётке;<br /> - внести у/з в подготовленные группы на указанном сервере;<br /> - исключить у/з из подготовленных групп на указанном сервере;</p><p>Если передавать параметрами учётку, контроллер и даже перечень групп, то многие действия будут автоматизированы.</p><br /><p>Теоретически скрипт можно использовать и для того, чтобы облегчить включениеь у/з в группы последовательно на нескольких серверах, или для того, чтобы набор имеющихся групп у одного пользователя выдать другом. </p><p>Довольно удобно делать исключение из всех групп - скрипт не прерывает работу на предупреждения, если у вас нет прав на какую либо группу - не надо клацать на ОКей как в AD-оснастке.</p></div></div><p>Картинки и &quot;мурзилку&quot; можно увидеть здесь - <a href="https://sites.google.com/site/scripttools/home/run_select_groups_for_add-hta">sites.google.com/.../run_select_groups_for_add-hta</a></p><p>Сам код <strong>run_select_Groups_for_Add.hta</strong>:<br /></p><div class="fancy_spoiler_switcher"><div class="fancy_spoiler_switcher_header" data-lang-open="открыть спойлер" data-lang-close="скрыть спойлер"><strong>+</strong>&nbsp;открыть спойлер</div><div class="fancy_spoiler"><div class="codebox"><pre><code>
&lt;!-- Окно для управления группами учетной записи (пользователя или машины) на указанном контроллере.

Можно запускать из HTA-приложения в качестве ModelessDialog (см.ниже пример команды запуска) 
либо из любого другого приложения в качестве самостоятельного приложения (см.ниже параметры командной строки).

Позволяет:
 - получить группы у/з на контроллере (указанном явно либо текущем);
 - выбрать из полученных групп некоторые (или все) для их удаления (или выдачи другой учётной записи);
 - указать маску (начало имени) для выборки из AD группы - для последующего её добавления учётке;
 - внести у/з в подготовленные группы на указанном сервере;
 - исключить у/з из подготовленных групп на указанном сервере;
-------------------------------------------------------------

Параметры передаются одной строкой.  Синтаксис строки параметров &quot;своеобразный&quot;:

   &quot;УЗ[~comp][`Сервер[`Группа1[~Группа2[~....]]]]&quot;

где:
 - УЗ - учетная запись пользователя (один из аттрибутов: distinguishedName / samAccountName / mail / givenName sn / sn givenName) 
          или у/з машины (distinguishedName / cn);
 - &quot;~comp&quot; после УЗ - признак того, что у/з является компьютером, а не пользователем;
 - символ &quot;`&quot; - разделитель параметров в строке;
 - Сервер - контроллер, на котором производятся операции с группами;
 - Группа - добавляемая/удаляемая группа (синтаксис - distinguishedName), групп может быть целый перечень, 
    разделение групп между собой - символом &quot;~&quot;.
-------------------------------------------------------------- --&gt;

&lt;!--Примеры (VBScript) запуска из HTA-приложения диалога выбора и добавления групп в Моделесс-окне

window.showModelessDialog  _
    &quot;run_select_Groups_for_Add.hta&quot;, _
    sDN &amp; &quot;`&quot; &amp; sDC &amp; &quot;`&quot; &amp; listGrp, _
    &quot;dialogHeight:800px;dialogWidth:855px&quot;
&#039;
&#039;где: sDN - distinguishedName у/записи
&#039;     sDC - имя Domain Controller
&#039;     listGrp - список добавляемых/удадяемых групп (distinguishedName), в качестве разделителя - символ &quot;~&quot;

&#039; Запуск диалога просмотра групп пользователя для выбора и удаления из групп на указанном контроллере
window.showModelessDialog  _
    &quot;run_select_Groups_for_Add.hta&quot;, _
    &quot;PupkinV`myDC&quot;, _
    &quot;dialogHeight:800px;dialogWidth:855px&quot;

&#039; Запуск диалога для добавления указанной группы компьютеру (+ возможность выбора и удаления других групп) на указанном контроллере
window.showModelessDialog  _
    &quot;run_select_Groups_for_Add.hta&quot;, _
    &quot;pupkinPC001~comp`myDC`LDAP://CN=SI Soft1,OU=Software groups,OU=Groups,DC=myFirma,DC=com&quot;, _
    &quot;dialogHeight:800px;dialogWidth:855px&quot;
-------------------------------------------------------------- --&gt;



&lt;!--Примеры запуска не в виде диалогового окна, а из командной строки.

При таком старте вся строка с параметрами обязательно должна быть взята в кавычки - &quot;....&quot;.
Можно передавать все параметры и одной строкой и каждый из параметров отдельно брать в кавычки и разделять их пробелом:
     run_select_Groups_for_Add.hta &quot;УЗ[~comp]&quot; [&quot;Сервер&quot;] [&quot;Группы через ~-разделитель&quot;]

Запуск с указанием только лишь пользовательской у/з (логином):
  run_select_Groups_for_Add.hta &quot;PupkinV&quot;

Запуск с указанием пользовательской у/з (имейлом) и контроллера:
  run_select_Groups_for_Add.hta &quot;Vasia.Pupkin@myMail.com`myDC&quot;

Запуск с указанием пользовательской у/з (имейлом), контроллера и перечня групп:
  run_select_Groups_for_Add.hta &quot;Vasia.Pupkin@myMail.com`myDC`LDAP://CN=SI Soft1,OU=Software groups,OU=Groups,DC=myFirma,DC=com~LDAP://CN=SI Soft2,OU=Software groups,OU=Groups,DC=myFirma,DC=com&quot;
  run_select_Groups_for_Add.hta &quot;Vasia.Pupkin@myMail.com&quot; &quot;myDC&quot;
    
Запуск с указанием компьютерной у/з (имя машины) и контроллера:
  run_select_Groups_for_Add.hta &quot;pupkinPC001~comp`myDC&quot;

Запуск с указанием компьютерной у/з, контроллера и перечня групп:
  run_select_Groups_for_Add.hta &quot;pupkinPC001~comp&quot; &quot;myDC&quot; &quot;LDAP://CN=SI Soft1,OU=Software groups,OU=Groups,DC=myFirma,DC=com~LDAP://CN=SI Soft2,OU=Software groups,OU=Groups,DC=myFirma,DC=com&quot;

    --&gt;

&lt;HTML&gt;
&lt;HEAD&gt;
&lt;META content=&quot;text/html; charset=utf-8&quot; http-equiv=Content-Type&gt;
&lt;TITLE&gt;AD-selection groups to add them to account (v.2 by 29.11.2013)&lt;/TITLE&gt;
&lt;HTA:APPLICATION
APPLICATION ID=&quot;oSelectGroupsHTA&quot;
APPLICATIONNAME=&quot;select_Groups&quot;
BORDER = &quot;thin&quot;
CAPTION = &quot;yes&quot;
RESIZE = &quot;no&quot;
SHOWINTASKBAR = &quot;yes&quot;
SINGLEINSTANCE = &quot;no&quot;
SYSMENU = &quot;yes&quot;
WINDOWSTATE = &quot;normal&quot;
SCROLL = &quot;no&quot;
SCROLLFLAT = &quot;yes&quot;
VERSION = &quot;2.0&quot;
INNERBORDER = &quot;no&quot;
SELECTION = &quot;yes&quot;
MAXIMIZEBUTTON = &quot;no&quot;
MINIMIZEBUTTON = &quot;yes&quot;
NAVIGABLE = &quot;yes&quot;
CONTEXTMENU = &quot;yes&quot;
BORDERSTYLE = &quot;normal&quot;&gt;
&lt;/HTA&gt;

&lt;style&gt;
select
{
   font-family: verdana;
   font-size: 7pt;
   width: 310px;
   margin-left: 0px;
}

.button
{
 font-family: verdana;
 font-size: 8pt;
}

.frameLog 
{
    width: 820px;
    height: 378px;
    border: 1px solid #000;
    overflow: auto;
        margin-left: 1px;
}

*{font-family:Verdana;font-size:11;}
&lt;/style&gt;

&lt;SCRIPT LANGUAGE=&quot;JScript&quot;&gt;

var wshShell = new ActiveXObject( &#039;WScript.Shell&#039; );

////// События перехвата клавиш приложения
document.attachEvent(&quot;onkeydown&quot;, ue_body_onkeydown);

function ue_body_onkeydown(){
// F2 - запись в группы
if (event.keyCode==113) ue_btDone();

// F3 - перечитывание групп у/з
if (event.keyCode==114) uf_Reload();

// F8 - признак удаления из групп
if (event.keyCode==119) idLbl_ChkDel.click();
}

// добавление строки в протокол и форсирование перерисовки окна программы
function uf_outWrite( pTxt ) {
    idDivLog.insertAdjacentHTML(&quot;beforeEnd&quot;,pTxt)
    wshShell.Run( &#039;ping /?&#039; , 0 , true );
}

// возвращает полученную строку после преобразования в массив, сортировки и обратного преобразоваия в строку
// pDelim - символ разделения элементов массива
function uf_sortList (pWS, pDelim)
{
    arrWS = pWS.split(pDelim);
    arrWS.sort();
    var ret = &quot;&quot;;
    ret = arrWS.join(pDelim);
    return ret;
}

// Выбрать все группы учетной записи
function uf_allUsersGroups(){
    var objSel = document.getElementById( &quot;idSelectorUsersGroups&quot; );
    var objTA  = document.getElementById( &quot;ta_addedGrp&quot; );
    var sVal;
    for (var i=0; i&lt;objSel.length; i++) {
        sVal = objSel.options[i].value;
        if (sVal.length&gt;0) {
            objTA.value += &quot;\r\n&quot;;
            objTA.value += sVal;
        }
    }
}

// Изменение размеров и центровка окна (вызывается при вызове не в качестве диалога)
function uf_resizeMyWin(){
    var winWidth=865; // ширина окна
    var winHeight=850; // высота окна
    
    // изменяем размер
    window.resizeTo(winWidth, winHeight);

    // окно в центр экрана // http://habrahabr.ru/post/40707/
    var winPosX=screen.width/2-winWidth/2;
    var winPosY=screen.height/2-winHeight/2 - 20 ; // чуть приподнимаем
    window.moveTo(winPosX, winPosY);
}
&lt;/SCRIPT&gt;


&lt;SCRIPT LANGUAGE=&quot;VBScript&quot;&gt;

&#039; ----- константы глобальные для всего приложения
Const ADS_SERVER_BIND = &amp;h200

Sub Window_Onload
    ta_addedGrp.Value = &quot;&quot;
    
    Dim sArg : sArg = &quot;&quot; &#039; строка с параметрами (либо из window.dialogArguments, либо .commandLine)&#039;
    
    &#039; --- по идее в window.dialogArguments должно быть 3 аргумента разделенных символом &quot;`&quot; 
    Dim winArg : winArg = &quot;&quot;
    On Error Resume Next
    &#039; MsgBox window.dialogArguments,, &quot;window.dialogArguments&quot; &#039;&#039;&#039;for debug
    winArg = window.dialogArguments
    On Error GoTo 0
    
    Dim pArray &#039; массив для разбора параметров&#039;
    Dim pArrDn
    
    If Len(winArg)&gt;0 Then
        sArg = winArg
    Else
        &#039; При вызове из командной командной строки с параметрами, размеры окна командой запуска не передаются - меняем на свои
        uf_resizeMyWin
        
        &#039; параметры командной строки запуска
        &#039; from http://blogs.technet.com/b/heyscriptingguy/archive/2005/04/20/how-can-i-pass-command-line-variables-to-an-hta-when-it-starts.aspx&#039;
        pArray = Split(oSelectGroupsHTA.commandLine, chr(34))
    For i = 3 to (Ubound(pArray) - 1) Step 2
            &#039; сливаем все аргументы в одну строку, если строка была разбита на части, а части были окаймлены кавычками&#039;
            If Left(pArray(i),1)&lt;&gt;&quot;`&quot; AND Len(sArg)&gt;0 then sArg = sArg &amp; &quot;`&quot;
            sArg = sArg &amp; pArray(i)
    Next
        &#039; Msgbox &quot;commandLine = &quot; &amp; oSelectGroupsHTA.commandLine &amp; vbCrLf &amp; vbCrLf &amp; &quot;sArg = &quot; &amp; sArg &#039;&#039;&#039;for debug
    End IF

    If Len(sArg)&gt;0 Then
        &#039; окно вызывалось в качестве диалога &#039;
        On Error Resume Next
        pArray = Split(sArg, &quot;`&quot;)
        If IsArray(pArray) Then
            &#039; 1-й -- &quot;distinguishedName&quot; добавляемой в группы у/з и через &quot;~&quot; - тип учетной записи&#039;
            pArrDn = Split(pArray(0), &quot;~&quot;)
            idAcc.value = pArrDn(0)
            &#039; --- учитываем в distinguishedName у/з возможный признак типа &quot;компьютер&quot; - наличие завершающей строки &quot;~comp&quot;
            If UBound(pArrDn)=1 Then
                If pArrDn(1)=&quot;comp&quot; then rbtTypeAcc(1).checked = True
            End IF
            &#039; 2-й -- имя контроллера домена, на котором будет выполнятся запись в группы
            idDC.value  = pArray(1) 
            &#039; 3-й -- перечень групп, разделение - символ &quot;~&quot;
            ta_addedGrp.Value = Replace(pArray(2),&quot;~&quot;, vbCrLf) 
        End IF
        On Error GoTo 0
    End IF

    If Len(idAcc.value)&gt;0 Then
        uf_Reload() &#039; формируем список имеющихся у у/з групп&#039;
    Else
        idSpnUsersGrpSel.InnerHTML = &quot;&lt;SELECT size=&#039;12&#039; id=&#039;idSelectorUsersGroups&#039; &quot; &amp;_
            &quot;title=&#039;Enter / dblclick - добавление группы к выбранным, например, для удаления пользователя из групп&#039; &quot; &amp;_
            &quot;&gt;&quot; &amp;_
            &quot;&lt;OPTION VALUE=&#039;&#039;/&gt;-- Select an Existing Group for Removing --&lt;/SELECT&gt;&quot;
    End IF

    &#039; --- выборку не выполняем - создаем пустой SELECT&#039;
    idSpnGrpSelector.InnerHTML = &quot;&lt;SELECT id=&#039;selectGrp&#039; NAME=&#039;FindedGrp&#039; size=&#039;12&#039; &quot; &amp;_
            &quot;title=&#039;Результат выборки из AD групп по указанной выше маске поиска&#039; &quot; &amp;_
            &quot;&gt;&quot; &amp;_
            &quot;&lt;OPTION VALUE=&#039;&#039;/&gt;-- Select an Group for Add/Remove --&lt;/SELECT&gt;&quot;
    document.all.idGrpName.select &#039; выделяем текст в поле ввода имени искомой группы&#039;
    document.all.idGrpName.focus()
End SUB

&#039;----------------------------------------------------------&#039;
&#039; Builds a &lt;SELECT&gt; form with finded groups in canonical format
&#039; pName - condition to seek for groups (by their name).
&#039;    Example: &quot;AND (name=&#039;....*&#039; OR ..... )&quot;
&#039;----------------------------------------------------------&#039;
Function SelectFindedGrp ( pName )

    Dim defaultNC, AdConn, AdComm, AdRs, AdQuery
    SelectFindedGrp = _
        &quot;&lt;SELECT id=&#039;selectGrp&#039; NAME=&#039;FindedGrp&#039; SIZE=&#039;12&#039; &quot; &amp;_
        &quot;onkeypress=&#039;ue_keySelect();&#039; &quot; &amp;_
        &quot;ondblclick=&#039;ue_prompt();&#039; &quot; &amp;_
        &quot;title=&#039;Enter / dblclick - добавление группы к выбранным&#039; &quot; &amp;_
        &quot;&gt;&quot; &amp;_
        &quot;&lt;OPTION VALUE=&#039;&#039;/&gt;-- Select an Group for Add/Remove --&quot;
    defaultNC = GetObject(&quot;LDAP://RootDSE&quot;).Get(&quot;DefaultNamingContext&quot;)
    AdQuery = &quot;SELECT AdsPath, cn &quot; &amp; _
                    &quot; FROM &#039;LDAP://&quot; &amp; defaultNC &amp; &quot;&#039;&quot; &amp; _
                    &quot; WHERE objectCategory=&#039;group&#039; &quot; &amp; pName
                    
    &#039;-------------------------------------------------------------------&#039;
    &#039; Create ADOBO connection and command objects and set search options&#039;
    &#039;-------------------------------------------------------------------&#039;
    Set AdConn = CreateObject(&quot;ADODB.Connection&quot;)
    AdConn.Provider = &quot;ADsDSOObject&quot;
    AdConn.Open &quot;Active Directory Provider&quot;
    Set AdComm = CreateObject(&quot;ADODB.Command&quot;)
    AdComm.ActiveConnection = AdConn
    AdComm.Properties(&quot;SearchScope&quot;) = 2
    AdComm.Properties(&quot;Page Size&quot;) = 500
    AdComm.Properties(&quot;Sort On&quot;) = &quot;cn&quot; 
    &#039;---------------------------------------&#039;
    &#039; Set query text and execute the query. &#039;
    &#039;---------------------------------------&#039;
    AdComm.CommandText = AdQuery
    Set AdRs = AdComm.Execute
    If Not AdRs.EOF Then
        With AdRs
            While Not .EOF
                AdsPath = .Fields(&quot;AdsPath&quot;)
                canonicalName = .Fields(&quot;cn&quot;)
                SelectFindedGrp = SelectFindedGrp &amp; &quot;&lt;OPTION VALUE=&#039;&quot; &amp; AdsPath &amp; &quot;&#039;/&gt;&quot; &amp; canonicalName &amp; vbCrLf
                .MoveNext
            Wend
        End With
    End IF &#039;Not AdRs.EOF&#039;

    Set AdConn = Nothing
    Set AdComm = Nothing
    Set AdRs = Nothing
    
    SelectFindedGrp = SelectFindedGrp &amp; &quot;&lt;/SELECT&gt;&quot;
End Function

&#039; Формируем список с группами у/з&#039;
Sub uf_Reload
    
    If Len( idAcc.value )&gt;0 Then
        If NOT uf_verifyCN() Then EXIT SUB &#039; не пройден контроль указанного значения у/з&#039;
        
        Dim objConnection, objCommand, objRSet
        Set objConnection = CreateObject(&quot;ADODB.Connection&quot;)
        objConnection.Provider = &quot;ADsDSOObject&quot;
        objConnection.Properties(&quot;ADSI Flag&quot;) = ADS_SERVER_BIND
        objConnection.Open &quot;Active Directory Provider&quot;
        Set objCommand = CreateObject(&quot;ADODB.Command&quot;)
        Set objCommand.ActiveConnection = objConnection
        objCommand.Properties(&quot;Page Size&quot;) = 1000
        objCommand.Properties(&quot;Timeout&quot;) = 30
        
        &#039; Если выбрана вторая кнопка - rbtTypeAcc(1) - значит это не пользовательская у/з, а - компьютерная&#039;
        Dim sFndCategory : sFndCategory = &quot;(objectCategory=person)(objectClass=user)&quot;
        If rbtTypeAcc(1).checked = true Then
            sFndCategory = &quot;(objectCategory=Computer)&quot;
        End IF
        
        Dim sCN : sCN = uf_GetCN_fromStr (idAcc.value) &#039; получаем значение cn из distinguishedName&#039;
        Dim sFndExpr : sFndExpr = &quot;cn=&quot; &amp; sCN
        
        objCommand.CommandText = _
            &quot;&lt;LDAP://&quot; &amp; idDC.value &amp; &quot;&gt;;&quot; &amp;_
            &quot;(&amp;&quot; &amp; sFndCategory &amp; &quot;(&quot; &amp; sFndExpr &amp; &quot;)&quot; &amp;_
            &quot;);memberof;Subtree&quot;
        &#039; --- Запрос к AD с обработкой ошибки подключения&#039;
        On Error Resume Next
        Set objRSet = objCommand.Execute
        If Err.Number &lt;&gt; 0 Then
            uf_outWrite _
                time() &amp; &quot;&amp;nbsp;&amp;nbsp;&lt;b&gt;Ошибка работы с AD.&lt;/b&gt;&amp;nbsp; &lt;font color=&#039;red&#039;&gt;Error! #&quot; &amp; _
                CStr(Err.Number) &amp; &quot; Desc.: &lt;b&gt;&quot; &amp; Err.Description &amp; &quot;&lt;/b&gt;&lt;/font&gt;&lt;br&gt;&lt;br&gt;&quot;
            On Error GoTo 0
        else
            On Error GoTo 0
            If objRSet.RecordCount &lt;&gt; 1 Then
                MsgBox &quot;Не найдена учетная запись - &quot; &amp; sCN &amp; vbCr &amp; vbCr &amp; objCommand.CommandText,_
                    vbExclamation, &quot;Неудачный поиск в AD&quot;
                EXIT SUB
            End IF
            objRSet.MoveFirst
            
            &#039;--- группы юзера&#039;
            Dim iCnt : iCnt = 0
            Dim sOption : sOption = &quot;&quot;
            Dim sMemberOf
            Dim aMemberOf : aMemberOf = objRSet.Fields(&quot;memberof&quot;)
            If IsArray(aMemberOf) Then
                For iMemb = 0 to UBound(aMemberOf)
                    aMemberOf(iMemb) = &quot;LDAP://&quot; &amp; aMemberOf(iMemb)
                NEXT
                sMemberOf = Join(aMemberOf, vbCr)
                sMemberOf = uf_sortList (sMemberOf, vbCr) &#039;сортируем список групп&#039;
                aMemberOf = Split(sMemberOf, vbCr) &#039;возвращаем в массив после сортировки
                
                For iMemb = 0 to UBound(aMemberOf)
                    sOption = sOption &amp; &quot;&lt;OPTION VALUE=&#039;&quot; &amp; aMemberOf(iMemb) &amp; &quot;&#039;/&gt;&quot; &amp; uf_GetCN_fromStr( aMemberOf(iMemb) ) &amp; vbCrLf
                    iCnt = iCnt + 1
                NEXT
            else &#039;IsArray(aMemberOf)&#039; - групп у пользователя еще нет
                sMemberOf = &quot;Учетка ни в какие группы не входит!&quot;
                sOption = sOption &amp; &quot;&lt;OPTION /&gt;&quot; &amp; sMemberOf &amp; vbCrLf
            End IF
            Set objRSet = Nothing
            Set objCommand = Nothing
            Set objConnection = Nothing
            uf_outWrite _
                &quot;Получено &quot; &amp; time() &amp; &quot; - &lt;b&gt;&quot; &amp; CStr(iCnt) &amp; &quot;&lt;/b&gt; гр. учетной записи [&quot; &amp; sFndExpr &amp; &quot;]&lt;br&gt;&quot;
        End IF &#039;err&lt;&gt;0&#039;
        sOption = _
            &quot;&lt;SELECT id=&#039;idSelectorUsersGroups&#039; SIZE=&#039;12&#039; &quot; &amp;_
            &quot;onkeypress=&#039;ue_keySelectUsrGrp();&#039; &quot; &amp;_
            &quot;ondblclick=&#039;ue_promptUsrGrp();&#039; &quot; &amp;_
            &quot;title=&#039;Enter / dblclick - добавление группы к выбранным&#039; &quot; &amp;_
            &quot;&gt;&quot; &amp;_
            &quot;&lt;OPTION VALUE=&#039;&#039;/&gt;-- Select an Existing Group for Removing --&quot; &amp; sOption &amp; &quot;&lt;/SELECT&gt;&quot;
        idSpnUsersGrpSel.innerHTML = sOption
    End IF &#039;Len(sLDAP)&gt;0&#039;
    
End SUB

&#039; --- uf_GetCN_fromStr() ----------------------------------------------- 
&#039; получение из строки &quot;CN&quot; - текст от &quot;CN=&quot; до &quot;,&quot;
&#039; &quot;CN=&quot; может быть в любом месте параметра
Function uf_GetCN_fromStr (sParam)
    Dim ret, iPosBeg, iPosEnd
    ret = sParam
    iPosBeg = InStr(sParam,&quot;CN=&quot;)
    If iPosBeg&gt;0 Then
        iPosEnd = InStr(iPosBeg, sParam, &quot;,&quot;)
        If iPosEnd&gt;0 Then
            ret = Mid(sParam, iPosBeg + 3, iPosEnd - (iPosBeg + 3) )
        End IF
    End IF
    uf_GetCN_fromStr = ret
End Function
&#039;--------------------------------------------------------------

&#039; --- uf_verifyCN() ----------------------------------------------- 
&#039; Проверка наличия &quot;CN=&quot; в поле учетной записи. Установка контроллера, если не был указан.
&#039; Например, после ручного редактирования у/з или передачи его параметром не в формате distinguishedName.
Function uf_verifyCN ()

    Dim sAcc : sAcc = idAcc.value
    If Len(sAcc)=0 Then
        uf_outWrite &quot;&lt;font color=&#039;darkred&#039;&gt;Не указана у/з !&lt;/font&gt;&lt;br&gt;&quot;
        MsgBox &quot;Не указана учетная запись&quot;, vbCritical, &quot;Контроль у/з&quot;
        uf_verifyCN = False
    else
        If Len(idDC.value)=0 Then &#039; не указан сервер DC - определяем свой&#039;
            Dim objRoot, sSrvName
            Set objRoot = GetObject(&quot;LDAP://RootDSE&quot;)
            sSrvName = objRoot.Get(&quot;ServerName&quot;) 
            If InStr(sSrvName,&quot;,&quot;)&gt;0 Then sSrvName = Left(sSrvName, InStr(sSrvName,&quot;,&quot;) -1 )
            If InStr(sSrvName,&quot;=&quot;)&gt;0 Then sSrvName = Right(sSrvName, Len(sSrvName) - InStr(sSrvName,&quot;=&quot;) )
            &#039;протоколируем поиск DC&#039;
            uf_outWrite &quot;&lt;hr&gt;Не был указан DC! Определяем текущий: &lt;b&gt;&quot; &amp; sSrvName &amp;&quot;&lt;/b&gt;&quot;
            idDC.value = sSrvName
            Set objRoot = Nothing
        End IF

        If UCase(Left(sAcc,3))=&quot;CN=&quot; Then
            uf_verifyCN = True &#039; раз строка начинается на CN=, то предполагаем, что это уже корректный distinguishedName&#039;
        Else
        
            &#039; --- Формирование условия поиска и запрос в AD указанной у/з, определение однозначности найденного значения
            
            Dim objConnection, objCommand, objRSet
            Set objConnection = CreateObject(&quot;ADODB.Connection&quot;)
            objConnection.Provider = &quot;ADsDSOObject&quot;
            objConnection.Properties(&quot;ADSI Flag&quot;) = ADS_SERVER_BIND
            objConnection.Open &quot;Active Directory Provider&quot;
            Set objCommand = CreateObject(&quot;ADODB.Command&quot;)
            Set objCommand.ActiveConnection = objConnection
            objCommand.Properties(&quot;Page Size&quot;) = 1000
            objCommand.Properties(&quot;Timeout&quot;) = 30
            &#039; --- Формирование условия поиска &#039;
            &#039; Если выбрана вторая кнопка - rbtTypeAcc(1) - значит это не пользовательская у/з, а - компьютерная&#039;
            Dim sFndCategory, sFndExpr 
            If rbtTypeAcc(1).checked = true Then
                sFndCategory = &quot;(objectCategory=Computer)&quot;
                &#039; для машины вариантов нет - ищем только по ее имени&#039;
                sFndExpr = &quot;cn=&quot; &amp; sAcc
            else
                sFndCategory = &quot;(objectCategory=person)(objectClass=user)&quot;
                &#039; для пользователя есть варианты: могли указать: учетку / имейл / имя+фамилию / фамилию+имя&#039;
                If InStr(sAcc,&quot; &quot;)&gt;0 Then &#039; имеется пробел, проверяем - единственный ли он?&#039;
                    If InStr(sAcc,&quot; &quot;)=InStrRev(sAcc,&quot; &quot;) Then
                        &#039; ищем: имя+фамилию OR фамилию+имя&#039;
                        Dim arrNm : arrNm = Split(sAcc, &quot; &quot;)
                        sFndExpr = &quot;(|&quot; &amp; _
                            &quot;(&amp;(givenName=&quot; &amp; arrNm(0) &amp; &quot;)(sn=&quot; &amp; arrNm(1) &amp; &quot;))&quot; &amp; _
                            &quot;(&amp;(givenName=&quot; &amp; arrNm(1) &amp; &quot;)(sn=&quot; &amp; arrNm(0) &amp; &quot;))&quot; &amp; _
                            &quot;)&quot;
                    Else &#039; пробел в искомой строке не единственный, предположим, что это значение displayName / cn&#039;
                        sFndExpr = &quot;displayName=&quot; &amp; sAcc
                        sFndExpr = &quot;(|&quot; &amp; _
                            &quot;(displayName=&quot; &amp; sAcc &amp; &quot;)&quot; &amp; _
                            &quot;(cn=&quot; &amp; sAcc &amp; &quot;)&quot; &amp; _
                            &quot;)&quot;
                    End IF
                Else
                    If InStr(sAcc,&quot;@&quot;)&gt;0 Then &#039;видимо - это имейл&#039;
                        sFndExpr = &quot;mail=&quot; &amp; sAcc
                    Else &#039;возможно, что это логин&#039;
                        sFndExpr = &quot;samAccountName=&quot; &amp; sAcc
                    End IF
                End IF
            End IF
            
            &#039;--- поиск у/з&#039;
            objCommand.CommandText = _
                &quot;&lt;LDAP://&quot; &amp; idDC.value &amp; &quot;&gt;;&quot; &amp;_
                &quot;(&amp;&quot; &amp; sFndCategory &amp; &quot;(&quot; &amp; sFndExpr &amp; &quot;)&quot; &amp;_
                &quot;);distinguishedName;Subtree&quot;
            &#039;протоколируем строку поиска&#039;
            uf_outWrite &quot;&lt;hr&gt;&lt;b&gt;Поиск у/з:&lt;/b&gt;&lt;br&gt;&quot; &amp; Replace(Replace(objCommand.CommandText,&quot;&gt;&quot;,&quot;&amp;gt;&quot;),&quot;&lt;&quot;,&quot;&amp;lt;&quot;) &amp; &quot;&lt;br&gt;&quot;
            Set objRSet = objCommand.Execute
            uf_outWrite &quot;Количество записей в результате поиска: &lt;b&gt;&quot; &amp; CStr(objRSet.RecordCount) &amp; &quot;&lt;/b&gt;&lt;hr&gt;&quot;
            If objRSet.RecordCount &lt;&gt; 1 Then
                MsgBox &quot;Не найдена учетная запись - &quot; &amp; sAcc &amp; vbCr &amp; vbCr &amp; objCommand.CommandText,_
                    vbExclamation, &quot;Неудачный поиск в AD&quot;
                    uf_verifyCN = False
            else
                objRSet.MoveFirst
                idAcc.value = objRSet.Fields(&quot;distinguishedName&quot;).Value
                uf_verifyCN = True
            End IF
            
            Set objRSet = Nothing
            Set objCommand = Nothing
            Set objConnection = Nothing
        End IF
    
    End IF &#039;Len(sAcc)&#039;

End Function
&#039;--------------------------------------------------------------

&#039; нажатие на Enter в поле ввода у/з -- старт запроса групп у/з (и поиска самой у/з)&#039;
Sub ue_keyAccName
    If window.event.keyCode = 13 Then uf_Reload
End SUB

&#039; нажатие на Enter в поле ввода имени группы -- старт поиска группы&#039;
Sub ue_keyGrpName
    If window.event.keyCode = 13 Then uf_search
End SUB

&#039; переформируем Select новым AD-запросом с указанием фильтра с именем группы&#039;
Sub uf_search
    idGrpName.value = LTrim(idGrpName.value)
    If Len(idGrpName.value)&gt;0 Then
        idSpnGrpSelector.InnerHTML = SelectFindedGrp( &quot;AND (name=&#039;&quot; &amp; idGrpName.value &amp; &quot;*&#039;)&quot; )
        document.all.selectGrp.focus()
        document.all.selectGrp.selectedIndex = 1
        If document.all.selectGrp.length = 2 Then &#039; была найдена единственная группа - её и добавляем&#039;
            ue_prompt
        End IF
    End IF
End SUB


&#039; нажатие на Enter в Select-е -- добавление выбранной в списке группы&#039;
Sub ue_keySelect
    If window.event.keyCode = 13 Then ue_prompt
End SUB

&#039; добавляем выбранную группу в строку для возврата результата&#039;
Sub ue_prompt
    If Len(FindedGrp.value)&gt;0 Then
        If Len(ta_addedGrp.value)&gt;0 then ta_addedGrp.value = ta_addedGrp.value &amp; vbCrLf
        ta_addedGrp.value = ta_addedGrp.value &amp; FindedGrp.value
        document.all.idGrpName.focus()
        document.all.idGrpName.select &#039; выделяем текст в поле ввода имени искомой группы&#039;
        document.all.idDivQuit.style.display = &quot;none&quot; &#039; выключаем видимость кнопки выхода&#039;
    End IF
End SUB

&#039; нажатие на Enter в Select-е -- добавление выбранной в списке группы&#039;
Sub ue_keySelectUsrGrp
    If window.event.keyCode = 13 Then ue_promptUsrGrp
End SUB

&#039; добавляем выбранную группу в строку для возврата результата&#039;
Sub ue_promptUsrGrp
    If Len(idSelectorUsersGroups.value)&gt;0 Then
        If Len(ta_addedGrp.value)&gt;0 then ta_addedGrp.value = ta_addedGrp.value &amp; vbCrLf
        ta_addedGrp.value = ta_addedGrp.value &amp; idSelectorUsersGroups.value
        document.all.idDivQuit.style.display = &quot;none&quot; &#039; выключаем видимость кнопки выхода&#039;
    End IF
End SUB

&#039; --- запись у/з в группы или удаление из групп&#039;
Sub ue_btDone
    idDC.value  = Trim (idDC.value)
    idAcc.value = Trim (idAcc.value)
    If NOT uf_verifyCN() Then EXIT SUB &#039; не пройден контроль указанного значения у/з&#039;
    
    uf_outWrite &quot;&lt;i&gt;Writing to AD...&lt;/i&gt;&amp;nbsp;&quot;
    id_btWrite.focus()
    
    &#039; --- настройка работы с группами AD - учет включенного признака удаления из групп
    Const ADS_PROPERTY_APPEND = 3
    Const ADS_PROPERTY_DELETE = 4
    Dim iType, sType
    iType = ADS_PROPERTY_APPEND
    sType = &quot;Added&quot;
    If idChkDel.checked Then
        If MsgBox(&quot;Удалять у/з из групп ?&quot;, vbQuestion + vbOkCancel, &quot;Подтверждение удаления&quot;)=vbOK then 
            iType = ADS_PROPERTY_DELETE
            sType = &quot;Removed&quot;
        else
            EXIT SUB
        End IF
    End IF
    If iType = ADS_PROPERTY_APPEND Then
        uf_outWrite &quot;&lt;b&gt;Старт добавления в группы&lt;/b&gt;&amp;nbsp;&quot; &amp; Time() &amp; &quot;&lt;hr&gt;&quot;
    Else
        uf_outWrite &quot;&lt;b&gt;Старт удаления из групп&lt;/b&gt;&amp;nbsp;&quot; &amp; Time() &amp; &quot;&lt;hr&gt;&quot;
    End IF
    
    On Error Resume Next
    
    Dim iCntOK, iCntErr : iCntOK = 0 : iCntErr = 0 &#039;Счетчики успешности записи в группы&#039;
    
    &#039; --- Формируем массив с выбранными группами и проходим по ним циклом&#039;
    Dim grpArray, i, sLDAP, objGroup, strReturn
    strReturn = ta_addedGrp.Value
    grpArray = Split(strReturn, vbCrLf)
    
    For i=0 To UBound(grpArray)
        sLDAP = grpArray (i)
        If Len(sLDAP)&gt;0 Then
            &#039; Добавляем имя DC, если таковое было указано&#039;
            If Len(idDC.value)&gt;0 then sLDAP = Replace(sLDAP, &quot;://&quot;, &quot;://&quot; &amp; idDC.value &amp; &quot;/&quot;)
            uf_outWrite sLDAP &amp; &quot;&lt;br&gt;&quot;
            
            Err.Clear
            Set objGroup = GetObject ( sLDAP ) 
            objGroup.PutEx iType, &quot;member&quot;, Array( idAcc.value)
            objGroup.SetInfo
            If Err.Number=0 Then
                uf_outWrite &quot;&amp;nbsp;&amp;nbsp;&lt;font color=&#039;green&#039;&gt;&lt;b&gt;&quot; &amp;sType&amp; &quot;.&lt;/b&gt;&lt;/font&gt;&lt;br&gt;&lt;br&gt;&quot;
                iCntOK = iCntOK + 1
            Else
                uf_outWrite _
                    &quot;&amp;nbsp;&amp;nbsp;&lt;font color=&#039;red&#039;&gt;Error! #&quot; &amp; CStr(Err.Number) &amp; &quot; Desc.: &lt;b&gt;&quot; &amp; Err.Description &amp; &quot;&lt;/b&gt;&lt;/font&gt;&lt;br&gt;&lt;br&gt;&quot;
                iCntErr = iCntErr + 1
            End IF
        End IF
        &#039; Включаем отображение кнопки &quot;Quit&quot;, но саму ее до окончания записи в группы дизейблим&#039;
        document.all.idDivQuit.style.display = &quot;block&quot;
        document.all.quitbutton.disabled = True
        document.all.quitbutton.focus()
    Next
    
    On Error GoTo 0
    If document.all.idDivQuit.style.display = &quot;block&quot; Then
        document.all.quitbutton.disabled = False
    End IF
    uf_outWrite &quot;&lt;span style=&#039;width:50%&#039;&gt;&lt;b&gt;Завершение работы с группами&lt;/b&gt;&amp;nbsp;&quot; &amp; Time() &amp;&quot;&lt;/span&gt;&lt;i&gt;&quot; &amp;_
        &quot;&amp;nbsp;Запись успешна: &lt;font color=&#039;green&#039;&gt;&lt;b&gt;&quot; &amp; CStr(iCntOK) &amp; &quot;&lt;/b&gt;&lt;/font&gt;&quot; &amp;_
        &quot;&amp;nbsp;Ошибок записи: &lt;font color=&#039;red&#039;&gt;&lt;b&gt;&quot; &amp; CStr(iCntErr) &amp; &quot;&lt;/b&gt;&lt;/font&gt;&quot; &amp;_
        &quot;&lt;/i&gt;&lt;hr&gt;&quot;
    uf_Reload() &#039; формируем список имеющихся у пользователя групп&#039;
    If document.all.idDivQuit.style.display = &quot;block&quot; Then
        document.all.quitbutton.focus()
    End IF
End Sub


&lt;/SCRIPT&gt;
&lt;/HEAD&gt;

&lt;BODY bgcolor=&quot;#E5ECF9&quot;&gt;
&lt;table&gt;
    &lt;tr&gt;
        &lt;td width=&quot;22%&quot; align=&quot;Right&quot;&gt;Искомая группа (маска):&lt;br&gt;
        (Enter - поиск)&lt;/td&gt;
        &lt;td&gt;
            &lt;input type=&quot;text&quot; id=idGrpName size=&quot;20&quot; value = &quot;si sql &quot; 
                title=&quot;Ввод начала имени искомой группы. &amp;#13;&amp;#13;&lt;Enter&gt;- поиск введенного выражения&quot;
                onkeypress=&quot;ue_keyGrpName();&quot;&gt;
                &lt;input class=&quot;button&quot; type=&quot;button&quot; value=&quot;Search in AD&quot;
                onClick=&quot;uf_search();&quot; TITLE=&quot;Поиск по маске&quot;&gt;
        &lt;/td&gt;
        &lt;td&gt;
            &lt;input class=&quot;button&quot; type=&quot;button&quot; id=&quot;id_btReload&quot; value=&quot;F3 - Reload memberships&quot;
                style=&quot;background-color: powderblue;&quot;
                onClick=&quot;uf_Reload();&quot; TITLE=&quot;Список существующих у учетной записи групп&quot;&gt;
            &lt;input class=&quot;button&quot; type=&quot;button&quot; value=&quot;Select All&quot;
                onClick=&quot;uf_allUsersGroups();&quot; TITLE=&quot;Выбрать все группы учетной записи&quot;&gt;
        &lt;/td&gt;
    &lt;/tr&gt; 
    &lt;tr&gt;
        &lt;td align=&quot;Right&quot;&gt;Выбор из списка групп&lt;br&gt;
        (Enter / dblclick)&lt;/td&gt;
        &lt;td&gt;&lt;SPAN ID=idSpnGrpSelector&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/td&gt;
        &lt;td&gt;&lt;SPAN ID=idSpnUsersGrpSel&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/td&gt;
    &lt;/tr&gt; 
    &lt;tr&gt;
        &lt;td align=&quot;Right&quot;&gt;
            &lt;b&gt;Выбранные группы:&lt;/b&gt; 
        &lt;/td&gt;
        &lt;td colspan=&quot;2&quot; align=&quot;Right&quot;&gt;
            &lt;input class=&quot;button&quot; type=&quot;button&quot; value=&quot;Clear List&quot; 
                onClick=&quot;document.getElementById(&#039;ta_addedGrp&#039;).value=&#039;&#039;;&quot; TITLE=&quot;Очистка списка выбранных групп&quot;&gt;
        &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;td colspan=&quot;3&quot; align=&quot;center&quot;&gt;
            &lt;TEXTAREA cols=115 name=&quot;ta_addedGrp&quot; rows=10
            style=&quot;background-color: lavender; font-family: Courier New; font-size: 11;&quot;
            title=&quot;Список выбранных групп&quot;&gt;
            &lt;/TEXTAREA&gt;
        &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;td align=&quot;Right&quot;&gt;Учётная запись&lt;/td&gt;
        &lt;td colspan=&quot;2&quot;&gt;&lt;input type=&quot;text&quot; id=&quot;idAcc&quot; size=&quot;60&quot; value = &quot;&quot;
                onkeypress=&quot;ue_keyAccName();&quot;
                style=&quot;background-color: lavender; font-family: Courier New; font-size: 11;&quot;
                title=&quot;У/З добавляемая в выбранные группы (или для удаления из выбранных групп). &amp;#13;&amp;#13;Указывать компьютер - по имени, пользователя - по его логину, и-мейлу, имени_фамилии, фамилии_имени. &amp;#13;&amp;#13;&lt;Enter&gt; - поиск у/з.&quot;&gt;
            &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
            &lt;LABEL title=&quot;Тип у/з - пользователь (настройка для &#039;Reload memberships&#039; и для поиска значения, указаного не формате distinguishedName)&quot;&gt;
                &lt;INPUT type=&quot;radio&quot; name=&quot;rbtTypeAcc&quot; value=&quot;user&quot; checked=&quot;checked&quot;&gt; User
            &lt;/LABEL&gt;
            &lt;LABEL title=&quot;Тип у/з - компьютер (настройка для &#039;Reload memberships)&#039;&quot;&gt;
                &lt;INPUT type=&quot;radio&quot; name=&quot;rbtTypeAcc&quot; value=&quot;comp&quot;&gt; Computer
            &lt;/LABEL&gt;
        &lt;/td&gt;
    &lt;/tr&gt; 
    &lt;tr&gt;
        &lt;td align=&quot;Right&quot;&gt;Контроллер домена&lt;br&gt;(для команд записи)&lt;/td&gt;
        &lt;td colspan=&quot;2&quot;&gt;&lt;input type=&quot;text&quot; id=&quot;idDC&quot; size=&quot;15&quot; value = &quot;&quot; 
                style=&quot;background-color: lavender; font-family: Courier New; font-size: 11;&quot;
                title=&quot;Контроллер, на котором будет выполняться добавление в группы&quot;&gt;
            &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
            &lt;LABEL title=&quot;Тип запроса к AD:[_] - добавление в группу / [x] - удаление из группы&quot;
            style=&quot;color:darkred;&quot; id=&quot;idLbl_ChkDel&quot;&gt;
            &lt;input type=checkbox id=&quot;idChkDel&quot; &gt; F8 -- Switch feature removing of the groups 
            &lt;/LABEL&gt;
      &lt;input class=&quot;button&quot; type=&quot;button&quot; id=&quot;id_btWrite&quot; value=&quot;F2 -- Write to groups&quot;
            style=&quot;background-color: lightskyblue;&quot;
            onClick=&quot;ue_btDone();&quot; TITLE=&quot;Внесение изменений в выбранные группы&quot;&gt;
        &lt;/td&gt;
    &lt;/tr&gt; 
    &lt;tr&gt;
        &lt;td colspan=&quot;3&quot; align=&quot;center&quot;&gt;
            &lt;!-- ----- Слой со стилем прокрутки протокола работы ---- --&gt;
            &lt;div style=&quot;font-family: verdana; font-size: 10;&quot;
                title=&quot;Протокол работы&quot;
                class=&quot;frameLog&quot;&gt;
                &lt;div id=idDivLog align=left&gt;&lt;/div&gt;
                &lt;div id=idDivQuit style=&quot;display:none&quot; align=center&gt;
                    &lt;input id=quitbutton class=&quot;button&quot; type=&quot;button&quot; value=&quot;Quit&quot; name=&quot;quit_button&quot; 
                        onClick=&quot;window.close();&quot; TITLE=&quot;Выход из диалога&quot;&gt;
                &lt;/div&gt;
            &lt;/div&gt;
        &lt;/td&gt;
    &lt;/tr&gt; 
            
&lt;/table&gt;

&lt;/BODY&gt;
&lt;/HTML&gt;


</code></pre></div></div></div>]]></content>
			<author>
				<name><![CDATA[Rom5]]></name>
				<uri>https://forum.script-coding.com/profile.php?id=5724</uri>
			</author>
			<updated>2013-11-29T15:02:42Z</updated>
			<id>https://forum.script-coding.com/viewtopic.php?pid=77711#p77711</id>
		</entry>
</feed>
