对于我的工作,我必须在VBScript中编写一个脚本,该脚本检索用户所属的所有组的列表,包括嵌套组,并取出将在整个列表中重复的嵌套组(以及缩进嵌套组,进一步缩进嵌套组的嵌套组等。)
我找到了一个脚本,它通过gallery.technet.microsoft.com上的Monimoy Sanyal获取用户所属的整个组列表,并尝试根据我的需要调整它。这是我编辑的脚本:
Option Explicit
Const ForReading = 1, ForWriting = 2, ForAppend = 8
Dim ObjUser, ObjRootDSE, ObjConn, ObjRS
Dim GroupCollection, ObjGroup
Dim StrUserName, StrDomName, StrSQL
Dim GroupsList
Dim WriteFile
GroupsList = ""
Set ObjRootDSE = GetObject("LDAP://RootDSE")
StrDomName = Trim(ObjRootDSE.Get("DefaultNamingContext"))
Set ObjRootDSE = Nothing
StrUserName = InputBox("Enter user login", "Info needed", "")
StrSQL = "Select ADsPath From 'LDAP://" & StrDomName & "' Where ObjectCategory = 'User' AND SAMAccountName = '" & StrUserName & "'"
Set ObjConn = CreateObject("ADODB.Connection")
ObjConn.Provider = "ADsDSOObject": ObjConn.Open "Active Directory Provider"
Set ObjRS = CreateObject("ADODB.Recordset")
ObjRS.Open StrSQL, ObjConn
If Not ObjRS.EOF Then
ObjRS.MoveLast: ObjRS.MoveFirst
Set ObjUser = GetObject (Trim(ObjRS.Fields("ADsPath").Value))
Set GroupCollection = ObjUser.Groups
WScript.Echo "Looking for groups " & StrUserName & " is member of. This may take some time..."
'Groups with direct membership, and calling recursive function for nested groups
For Each ObjGroup In GroupCollection
GroupsList = GroupsList + ObjGroup.CN + VbCrLf
CheckForNestedGroup ObjGroup
Next
Set ObjGroup = Nothing: Set GroupCollection = Nothing: Set ObjUser = Nothing
'Writing list in a file named Groups <username>.txt
Set WriteFile = WScript.CreateObject("WScript.Shell")
Dim fso, f
Set fso = CreateObject("Scripting.FileSystemObject")
Set f = fso.OpenTextFile("Groups " & StrUserName & ".txt", ForWriting,true)
f.write(GroupsList)
f.Close
WScript.Echo "You can find the list in the Groups " &StrUserName & ".txt file that has just been created."
Else
WScript.Echo "Couldn't find user " & StrUserName & " in AD."
End If
ObjRS.Close: Set ObjRS = Nothing
ObjConn.Close: Set ObjConn = Nothing
'Recursive fucntion
Private Sub CheckForNestedGroup(ObjThisGroupNestingCheck)
On Error Resume Next
Dim AllMembersCollection, StrMember, StrADsPath, ObjThisIsNestedGroup
AllMembersCollection = ObjThisGroupNestingCheck.GetEx("MemberOf")
For Each StrMember in AllMembersCollection
StrADsPath = "LDAP://" & StrMember
Set ObjThisIsNestedGroup = GetObject(StrADsPath)
'Not include a group in the list if it is already in the list (does not work for some reason?)
If InStr(GroupsList, ObjThisIsNestedGroup.CN) = 0 Then
GroupsList = GroupsList + vbTab + ObjThisIsNestedGroup.CN + VbCrLf
End If
'Recursion to look for nested groups and nested groups of nested groups and nested groups of nested groups of nested groups and...
CheckForNestedGroup ObjThisIsNestedGroup
Next
Set ObjThisIsNestedGroup = Nothing: Set StrMember = Nothing: Set AllMembersCollection = Nothing
End Sub
不是像原始脚本那样显示找到的EACH组的弹出窗口,而是将整个列表存储在字符串中(GroupsList = GroupsList + ObjGroup.CN + VbCrLf
表示直接组,GroupsList = GroupsList + vbTab + ObjThisIsNestedGroup.CN + VbCrLf
表示递归函数中的嵌套组,)一旦脚本完成查找组,它就会将String保存在文件中。 (f.write(GroupsList)
)
我的问题是,尽管递归函数中有If "InStr(GroupsList, ObjThisIsNestedGroup.CN) = 0
,我仍然发现自己在整个结果中都有大量的重复(我们的AD对于组来说是一种臃肿,它是一个包含许多嵌套组的巨大结构,其他嵌套组中的嵌套组等)并且检查似乎没有注意到已在GroupsList中找到ObjThisIsNestedGroup.CN。
我不知道如何正确实现缩进。
有什么想法吗?我对脚本非常陌生,所以如果答案显而易见,请原谅我。
答案 0 :(得分:0)
将组添加为Dictionary
的键,因此列表仅包含唯一名称,Join()
Keys
数组用于输出:
Set GroupsList = CreateObject("Scripting.Dictionary")
GroupsList.CompareMode = vbTextCompare 'make keys case-insensitive
...
GroupsList(ObjGroup.CN) = True
...
f.Write Join(GroupsList.Keys, vbNewLine)
答案 1 :(得分:0)
我找到了解决这两个问题的方法。好吧,第一个问题我不确定我是如何修复的,因为我只是在修改之后还原了代码然后它神奇地工作了。 对于增加的缩进,我声明了一个名为RecurCount的全局变量,每次调用递归过程时都会递增,并在过程后减少。然后,在程序中,我添加了一个For i = 0到RecurCount,它根据RecurCount添加了不同数量的vbTab。
这是工作程序:
Private Sub CheckForNestedGroup(ObjThisGroupNestingCheck)
On Error Resume Next
Dim AllMembersCollection, StrMember, StrADsPath, ObjThisIsNestedGroup, TabAdd, i
AllMembersCollection = ObjThisGroupNestingCheck.GetEx("MemberOf")
For Each StrMember in AllMembersCollection
If StrMember <> "" Then
StrADsPath = "LDAP://" & StrMember
Set ObjThisIsNestedGroup = GetObject(StrADsPath)
'If InStr(GroupsList, ObjThisIsNestedGroup.CN) = 0 Then (Uncomment this If and indent lines below to remove groups already in the list)
TabAdd = ""
For i = 0 to Recurcount
TabAdd = TabAdd & vbTab
Next
GroupsList = GroupsList & TabAdd & " " & ObjThisIsNestedGroup.CN & VbCrLf
'End If
'Recursion to include nested groups of nested groups
Recurcount = Recurcount + 1
CheckForNestedGroup ObjThisIsNestedGroup
Recurcount = Recurcount - 1
End If
Next
Set ObjThisIsNestedGroup = Nothing: Set StrMember = Nothing: Set AllMembersCollection = Nothing
End Sub
不要忘记在主脚本中使用Dim Recurcount,并在第一次调用CheckForNestedGroup之前将其设为0。