<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
	<title type="html"><![CDATA[Серый форум &mdash; VBScript: список групп домена, членом которых является пользователь]]></title>
	<link rel="self" href="https://forum.script-coding.com/extern.php?action=feed&amp;tid=4421&amp;type=atom" />
	<updated>2010-04-29T12:13:53Z</updated>
	<generator>PunBB</generator>
	<id>https://forum.script-coding.com/viewtopic.php?id=4421</id>
		<entry>
			<title type="html"><![CDATA[VBScript: список групп домена, членом которых является пользователь]]></title>
			<link rel="alternate" href="https://forum.script-coding.com/viewtopic.php?pid=35192#p35192" />
			<content type="html"><![CDATA[<p>Определение полного списка групп безопасности Windows-домена, членом которых (явно или косвенно) является пользователь домена.<br />Анализируются группы любого типа, входящие в структуру Active Directory.<br />Метод определения косвенного (&quot;вложенного&quot;) членства - итерационный просмотр.<br /></p><div class="codebox"><pre><code>Option Explicit
Dim objRoot &#039;объект для привязки к корню AD
Dim objGroups &#039;коллекция экземпляров класса &quot;Группа безопасности&quot;, членом которых пользователь является непосредственно
Dim objGroup &#039;экземпляр класса &quot;Группа безопасности&quot;
Dim strDomain &#039;имя домена в форматах (последовательно): NetBIOS, RDN
Dim strDC &#039;имя контроллера домена в формате NetBIOS
Dim strUser &#039;имя пользователя, для котрого определяется членство в группах
            &#039;(предполагается соответствие значению атрибута &quot;Common-Name&quot;)
Dim objWsNet &#039;экземпляр класса &quot;WScript.Network&quot;
Dim objWMI &#039;объект для привязки к WMI-пространству, содержащему классы &quot;Win32_UserAccount&quot; и &quot;Win32_GroupUser&quot;
Dim objCollection, objItem, intNumber &#039;коллекция, экземпляр, кол-во экземпляров (соответственно) класса &quot;Win32_UserAccount&quot;
Dim objConnection, objCommand, objRSet &#039;объекты для получения списка групп безопасности с помощью ADO
Dim strCommandText &#039;текст запроса к AD с помощью ADO
Dim strPath, strTemp, arrTemp &#039;вспомогательные переменные
Dim blnHasResult &#039;флаг-признак прекращения итерационного просмотра
                 &#039;(просмотр прекращается, если на текущем шаге итерации не найдено ни одной группы,
                 &#039;членом которой пользователь был бы косвенно)
Dim strList &#039;итоговый список групп, членом которых является пользователь

&#039;экземпляры класса &quot;Scripting.Dictionary&quot;
Dim dictResPositive &#039;уточняемый на каждом шаге итерации список групп, членом которых пользователь ЯВЛЯЕТСЯ
Dim dictResNegative &#039;уточняемый на каждом шаге итерации список групп, членом которых пользователь НЕ ЯВЛЯЕТСЯ
Dim dictTemp &#039;список групп, для которых на текущем шаге итерации проверяется косвенное членство пользователя

Const ADS_SCOPE_SUBTREE = 2 &#039;флаг-признак, указывающий область просмотра дерева AD (всё дерево полностью)

strUser = Trim(InputBox(&quot;Имя пользователя:&quot;))
If Len(strUser) &gt; 0 Then
    Set objWsNet = CreateObject(&quot;WScript.Network&quot;)
    strDomain = objWsNet.UserDomain
    Set objWsNet = Nothing
    Set objRoot = GetObject(&quot;LDAP://RootDSE&quot;)
    strDC = objRoot.Get(&quot;dnsHostName&quot;)
    On Error Resume Next
    Set objWMI = GetObject(&quot;winmgmts:{impersonationLevel=impersonate}!\\&quot; &amp; strDC &amp; &quot;\root\cimv2&quot;)
    If Err.Number = 0 Then
        Set objCollection = objWMI.ExecQuery(&quot;SELECT * FROM Win32_UserAccount WHERE Domain=&#039;&quot; &amp; strDomain &amp; &quot;&#039; AND Name=&#039;&quot; &amp; strUser &amp; &quot;&#039;&quot;)
        intNumber = objCollection.Count
        If intNumber &gt; 0 Then
            Set dictResPositive = CreateObject(&quot;Scripting.Dictionary&quot;)
            dictResPositive.CompareMode = 1
            Set dictResNegative = CreateObject(&quot;Scripting.Dictionary&quot;)
            dictResNegative.CompareMode = 1
            Set dictTemp = CreateObject(&quot;Scripting.Dictionary&quot;)
            dictTemp.CompareMode = 1
            &#039;WScript.Echo &quot;Ищем группы явного членства пользователя.&quot;
            For Each objItem In objCollection
                Set objGroups = objWMI.ExecQuery(&quot;ASSOCIATORS OF {Win32_UserAccount.Domain=&#039;&quot; &amp; strDomain &amp; _
                                &quot;&#039;,Name=&#039;&quot; &amp; strUser &amp; &quot;&#039;} WHERE AssocClass=Win32_GroupUser&quot;)
                If objGroups.Count &gt; 0 Then
                    For Each objGroup In objGroups
                        dictResPositive.Add objGroup.Name, True
                        &#039;WScript.Echo &quot;Пользователь - явный член группы &quot; &amp; objGroup.Name
                    Next
                End If
                Set objGroups = Nothing
            Next
            Set objItem = Nothing
            strDomain = objRoot.Get(&quot;DefaultNamingContext&quot;)
            Set objConnection = CreateObject(&quot;ADODB.Connection&quot;)
            objConnection.Provider = &quot;ADsDSOObject&quot;
            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
            objCommand.Properties(&quot;Searchscope&quot;) = ADS_SCOPE_SUBTREE
            strCommandText = &quot;SELECT ADsPath,cn FROM &#039;LDAP://&quot; &amp; strDomain &amp; &quot;&#039; WHERE objectCategory=&#039;Group&#039;&quot;
            objCommand.CommandText = strCommandText
            Set objRSet = objCommand.Execute
            objRSet.MoveFirst
            Do
                strPath = objRSet.Fields(&quot;ADsPath&quot;).Value
                If dictResPositive.Exists(objRSet.Fields(&quot;cn&quot;).Value) Then
                    dictTemp.Add strPath, vbNull
                    &#039;WScript.Echo &quot;[ + ] &quot; &amp; strPath
                Else
                    dictResNegative.Add strPath, False
                    &#039;WScript.Echo &quot;[ - ] &quot; &amp; strPath
                End If
                objRSet.MoveNext
            Loop While Not objRSet.EOF
            Set objRSet = Nothing
            Set objCommand = Nothing
            objConnection.Close
            Set objConnection = Nothing
            &#039;WScript.Echo vbNewLine &amp; &quot;Ищем группы косвенного членства пользователя.&quot;
            Do
                blnHasResult = False
                For Each strPath In dictResNegative.Keys
                    Set objGroup = GetObject(strPath)
                    &#039;WScript.Echo &quot;[ ? ] &quot; &amp; strPath
                    For Each strTemp In dictTemp.Keys
                        If objGroup.IsMember(strTemp) Then
                            dictResNegative.Item(strPath) = True
                            If Not blnHasResult Then blnHasResult = True
                        End If
                    Next
                Next
                If blnHasResult Then
                    dictTemp.RemoveAll
                    For Each strPath In dictResNegative.Keys
                        If dictResNegative.Item(strPath) Then
                            dictResPositive.Add strPath, False
                            dictTemp.Add strPath, vbNull
                            dictResNegative.Remove strPath
                            &#039;WScript.Echo &quot;[ + ] &quot; &amp; strPath
                        End If
                    Next
                End If
            Loop While blnHasResult
            Set objGroup = Nothing
            For Each strTemp In dictResPositive.Keys
                If dictResPositive.Item(strTemp) Then
                    strList = strList &amp; strTemp &amp; vbNewLine
                Else
                    arrTemp = Split(strTemp, &quot;,&quot;)
                    strList = strList &amp; Mid(arrTemp(0), 11) &amp; vbNewLine
                    Erase arrTemp
                End If
            Next
            dictResPositive.RemoveAll
            dictResNegative.RemoveAll
            dictTemp.RemoveAll
            Set dictResPositive = Nothing
            Set dictResNegative = Nothing
            Set dictTemp = Nothing
            WScript.Echo &quot;Итоговый список:&quot; &amp; vbNewLine &amp; &quot;===&quot; &amp; vbNewLine &amp; strList
        Else
            WScript.Echo &quot;Учётная запись &quot; &amp; UCase(strDomain &amp; &quot;\&quot; &amp; strUser) &amp; &quot; не обнаружена.&quot;
        End If
        Set objCollection = Nothing
    Else
        WScript.Echo &quot;Ошибка подключения к контроллеру &quot; &amp; UCase(strDC) &amp; &quot;: &quot; &amp; Err.Description
        Err.Clear
    End If
    Set objWMI = Nothing
    Set objRoot = Nothing
    On Error GoTo 0
End If
WScript.Quit 0</code></pre></div><p>Пример итогового списка для встроенной учётной записи администратора домена:<br /></p><div class="quotebox"><blockquote><p>Администраторы домена<br />Администраторы предприятия<br />Администраторы схемы<br />Владельцы-создатели групповой политики<br />Пользователи домена<br />Администраторы<br />Пользователи<br />Группа с запрещением репликации паролей RODC</p></blockquote></div><p>Примечания:<br />1) сценарий тестировался в домене с контроллерами на платформе Windows Server 2008 Std.;<br />2) для работы сценария необходимы полномочия администратора домена.</p>]]></content>
			<author>
				<name><![CDATA[Dmitrii]]></name>
				<uri>https://forum.script-coding.com/profile.php?id=13351</uri>
			</author>
			<updated>2010-04-29T12:13:53Z</updated>
			<id>https://forum.script-coding.com/viewtopic.php?pid=35192#p35192</id>
		</entry>
</feed>
