OK, so I have a number of scripts that do AD queries and other administrative reporting tasks, but I want to put them in a nice GUI, so I'm making an HTA. I figure this should be a cakewalk since most of the code and logic is already written, I just need to build the interfaces around it and account for all of the checkboxes, etc. But I have this piece of code that just plain doesn't work in the HTA, even though it does work perfectly fine when run from the command prompt.
The code is in a Sub that is supposed to get a collection of groups back from AD, and then check the groups to see if there are any members. Now these aren't normal memberships because these groups are used with Services for Unix, so the membership info is stored in an extended attribute called "memberUid" and the syntax is "IA5-String", and the string is semi-colon delimited (from ADSI Edit).
When I call the GetUnix Sub from within my HTA, it doesn't return any results. Now this code worked fine before I put it into the HTA, and I copied it out of the HTA and put it in a new file that looks like this:
And it returns the intended results. It literally is the same code.
The Windows Sub isn't used in this case, so I left it out. The Notify Sub just parses strUserMsg and generates either a text, file, csv, email, etc, so I left it out too.
I've added some comments during testing to try to find the error, and the problem seems to come from "strMember = objItem.GetEx("memberUid")". Even if there are no members to the group, it looks like it returns something for "memberUid", I'm not sure if it's empty, null, or whatever. But when the group does have members on the "memberUid" attribute it still doesn't return the actual account names (as long as I'm running it from within the HTA). At first I thought that maybe it was related to being inside a subroutine, which is why I made that separate test file. But that's not it. As near as I can tell, the only significant difference is that it's running from an HTA.
Does anyone have any ideas or suggestions?
One last clue, if I remove the "On Error Resume Next" I get different errors depending on how it's run. Via cscript.exe I get:
C:\test.vbs(22, 17) Active Directory: The directory property cannot be found in the cache.
Via the HTA I get:
Line: 68
Error: Illegal assignment: 'Item'
The line 68 is "strMember = objItem.GetEx("memberUid")", but I've noticed that HTA tend to report errors being on the line previous to where the error actually is (i.e., the last successfully completed line).
The code is in a Sub that is supposed to get a collection of groups back from AD, and then check the groups to see if there are any members. Now these aren't normal memberships because these groups are used with Services for Unix, so the membership info is stored in an extended attribute called "memberUid" and the syntax is "IA5-String", and the string is semi-colon delimited (from ADSI Edit).
Code:
Dim strEmailTo, strSMTPServer, strEmailFrom, strNotifyMessage, strUserMsg, dictResults, strDictReturn
Set dictResults = CreateObject("Scripting.Dictionary")
Sub RunReport
strUserMsg = ""
strNotifyMessage = ""
strSMTPServer = "mail.domain.com"
strEmailFrom = "address@domain.com"
strEmailTo = EmailAddrBox.Value
If OS(0).Checked Then
GetUnix
ElseIf OS(1).Checked Then
GetWindows
ElseIf OS(2).Checked Then
GetUnix ' Note: Because of the way that the Unix list checks for members, the Unix search must always come before any other.
GetWindows
End If
Notify
End Sub
Sub GetUnix
Set objConnection = CreateObject("ADODB.Connection")
objConnection.Open "Provider=ADsDSOObject;"
Set objCommand = CreateObject("ADODB.Command")
objCommand.ActiveConnection = objConnection
objCommand.CommandText = "<GC://EDITED FOR PRIVACY REASONS-BUT IT IS CORRECT>;(&(objectCategory=group)(name=*_root));distinguishedName,name;subtree"
Set objRecordSet = objCommand.Execute
If objRecordset.EOF Then
strUserMsg = strUserMsg & "No Unix groups found ending with '_root'."
Else
While Not objRecordset.EOF
strCN = objRecordset.Fields("distinguishedName")
On Error Resume Next
strTemp = ""
strMember = ""
Set objRootDSE = GetObject("LDAP://rootDSE")
Set objItem = GetObject("LDAP://" & strCN)
strMember = objItem.GetEx("memberUid")
For Each Item in strMember
strTemp = strTemp & Item & " "
Next
If strTemp = " " Then
Else
strUserMsg = strUserMsg & UCase(objRecordset.Fields("name")) & ":<br>Members:<br>"& strTemp & "<br>"
dictResults.Add UCase(objRecordset.Fields("name")), strTemp
'MsgBox UCase(objRecordset.Fields("name")) & "member ." & strTemp & "."
End If
objRecordset.MoveNext
Wend
End If
objConnection.Close
MsgBox strUserMsg
End Sub
Code:
strUserMsg = ""
GetUnix
Wscript.Echo strUserMsg
Sub GetUnix
Set objConnection = CreateObject("ADODB.Connection")
objConnection.Open "Provider=ADsDSOObject;"
Set objCommand = CreateObject("ADODB.Command")
objCommand.ActiveConnection = objConnection
objCommand.CommandText = "<GC://EDITED FOR PRIVACY REASONS-BUT IT IS CORRECT>;(&(objectCategory=group)(name=*_root));distinguishedName,name;subtree"
Set objRecordSet = objCommand.Execute
If objRecordset.EOF Then
strUserMsg = strUserMsg & "No Unix groups found ending with '_root'."
Else
While Not objRecordset.EOF
strCN = objRecordset.Fields("distinguishedName")
On Error Resume Next
strTemp = ""
strMember = ""
Set objRootDSE = GetObject("LDAP://rootDSE")
Set objItem = GetObject("LDAP://" & strCN)
strMember = objItem.GetEx("memberUid")
For Each Item in strMember
strTemp = strTemp & Item & " "
Next
If strTemp = " " Then
Else
strUserMsg = strUserMsg & UCase(objRecordset.Fields("name")) & ":<br>Members:<br>"& strTemp & "<br>"
'dictResults.Add UCase(objRecordset.Fields("name")), strTemp
'MsgBox UCase(objRecordset.Fields("name")) & "member ." & strTemp & "."
End If
objRecordset.MoveNext
Wend
End If
objConnection.Close
End Sub
And it returns the intended results. It literally is the same code.
The Windows Sub isn't used in this case, so I left it out. The Notify Sub just parses strUserMsg and generates either a text, file, csv, email, etc, so I left it out too.
I've added some comments during testing to try to find the error, and the problem seems to come from "strMember = objItem.GetEx("memberUid")". Even if there are no members to the group, it looks like it returns something for "memberUid", I'm not sure if it's empty, null, or whatever. But when the group does have members on the "memberUid" attribute it still doesn't return the actual account names (as long as I'm running it from within the HTA). At first I thought that maybe it was related to being inside a subroutine, which is why I made that separate test file. But that's not it. As near as I can tell, the only significant difference is that it's running from an HTA.
Does anyone have any ideas or suggestions?
One last clue, if I remove the "On Error Resume Next" I get different errors depending on how it's run. Via cscript.exe I get:
C:\test.vbs(22, 17) Active Directory: The directory property cannot be found in the cache.
Via the HTA I get:
Line: 68
Error: Illegal assignment: 'Item'
The line 68 is "strMember = objItem.GetEx("memberUid")", but I've noticed that HTA tend to report errors being on the line previous to where the error actually is (i.e., the last successfully completed line).