I am using this script to check to see if a user exists in AD. Since there is
already a connection to AD would it be possible to check for group membership
at the same time??...and if so..how?

Thanks

input = inputbox("Enter UserID")

if UserExists(Input,sDisplayName) then
wscript.echo "Found " & sDisplayName
else
wscript.echo "Not account found for 'Dave'"
end if


Function UserExists(sUser,sDisplayName)
Dim oConnection, oCommand, oRoot, sDNSDomain, sQuery, sFilter, oResults
UserExists = False
sDisplayName = sUser
On Error Resume Next
' Use ADO to search the domain for all users.
Set oConnection = CreateObject("ADODB.Connection")
Set oCommand = CreateObject("ADODB.Command")
oConnection.Provider = "ADsDSOOBject"
oConnection.Open "Active Directory Provider"
Set oCommand.ActiveConnection = oConnection
' Determine the DNS domain from the RootDSE object.
Set oRoot = GetObject("LDAP://RootDSE")
sDNSDomain = oRoot.Get("DefaultNamingContext")
sFilter = "(&(ObjectClass=user)(ObjectCategory=person)(samAccountName=" &
sUser & "))"
sQuery = "<LDAP://" & sDNSDomain & ">;" & sFilter & ";displayName;subtree"
oCommand.CommandText = sQuery
oCommand.Properties("Page Size") = 100
oCommand.Properties("Timeout") = 30
oCommand.Properties("Cache Results") = False
Set oResults = oCommand.Execute
Do Until oResults.EOF
if oResults.Fields("displayName") <> "" then
sDisplayName = oResults.Fields("displayName")
UserExists = True
End if
oResults.MoveNext
Loop
On Error Goto 0
End Function

Re: Find user group membership by Richard

Richard
Thu Oct 12 21:10:03 CDT 2006

Hi,

You have a few options. One is to add the memberOf attribute to the comma
delimited list of attribute values to be retrieved by the ADO query:

sQuery = "<LDAP://" & sDNSDomain & ">;" & sFilter &
";displayName,memberOf;subtree"

The memberOf attribute is a multi-valued collection of the Distinguished
Names of the groups the object is a direct member of (except the group
designated as the "primary" group, which is usually "Domain Users" for
users). You could return this collection, then loop through it and check if
the group of interest is included. Modify Function UserExists to return
arrGroups:
================
Function UserExists(sUser, sDisplayName, arrGroups)
....
sQuery = "<LDAP://" & sDNSDomain & ">;" & sFilter _
& ";displayName,memberOf;subtree"
....
Do Until oResults.EOF
sDisplay = oResults.Fields("displayName").Value & ""
arrGroups = oResults.Fields("memberOf").Value
UserExists = True
oResults.MoveNext
Loop
End Function
=========
I would recommend not using "On Error Resume Next". You can prevent an error
raised when there is no value assigned to displayName by appending a blank
string to the value retrieved, as above. This also means the function will
return True even though the user has no value for this attribute. sDisplay
will be a blank string. Then in the main part of the program:
=========
if UserExists(Input, sDisplayName, arrGroups) then
wscript.echo "Found " & sDisplayName
If IsNull(arrGroups) then
Wscript.Echo "No group memberships"
ElseIf (TypeName(arrGroups = "String") then
Wscript.Echo "Member of group " & arrGroups
Else
For Each strGroup In arrGroups
Wscript.Echo "Member of group " & strGroup
Next
End If
else
wscript.echo "Not account found for 'Dave'"
end if
=========
Note that ADO returns memberOf as an array if there is more than one group
DN in the collection. However, if there are no group memberships it will be
Null, and if there is one group it will have datatype "String". You must
account all possibilities. How you handle this depends on how many group
memberships you want to check. You could simply check each group as they are
enumerated, instead of echoing the names.

Another approach would be to return the distinguishedName of the user in
Function UserExists, then to check if this user is a member of a group, bind
to the group and use the IsMember method of the group object. You pass the
distinguishedName of the user to this method. Again, you add to the comma
delimited list of attribute values to be retrieved by the ADO query:

sQuery = "<LDAP://" & sDNSDomain & ">;" & sFilter _
& ";displayName,distinguishedName;subtree"

You would modify Function UserExists to return this value, perhaps as strDN.
Then, to check group membership:

Set objGroup = GetObject("LDAP://cn=TestGroup,ou=Sales,dc=MyDomain,dc=com")
If (objGroup.IsMember(strDN) = True) Then
Wscript.Echo "User is a member of the group"
Else
Wscript.Echo "User is NOT a member of the group"
End If

--
Richard
Microsoft MVP Scripting and ADSI
Hilltop Lab - http://www.rlmueller.net

"Bob A" <BobA@discussions.microsoft.com> wrote in message
news:76EE2F97-5843-4621-8DF4-37D9A3339F77@microsoft.com...
>I am using this script to check to see if a user exists in AD. Since there
>is
> already a connection to AD would it be possible to check for group
> membership
> at the same time??...and if so..how?
>
> Thanks
>
> input = inputbox("Enter UserID")
>
> if UserExists(Input,sDisplayName) then
> wscript.echo "Found " & sDisplayName
> else
> wscript.echo "Not account found for 'Dave'"
> end if
>
>
> Function UserExists(sUser,sDisplayName)
> Dim oConnection, oCommand, oRoot, sDNSDomain, sQuery, sFilter, oResults
> UserExists = False
> sDisplayName = sUser
> On Error Resume Next
> ' Use ADO to search the domain for all users.
> Set oConnection = CreateObject("ADODB.Connection")
> Set oCommand = CreateObject("ADODB.Command")
> oConnection.Provider = "ADsDSOOBject"
> oConnection.Open "Active Directory Provider"
> Set oCommand.ActiveConnection = oConnection
> ' Determine the DNS domain from the RootDSE object.
> Set oRoot = GetObject("LDAP://RootDSE")
> sDNSDomain = oRoot.Get("DefaultNamingContext")
> sFilter = "(&(ObjectClass=user)(ObjectCategory=person)(samAccountName=" &
> sUser & "))"
> sQuery = "<LDAP://" & sDNSDomain & ">;" & sFilter &
> ";displayName;subtree"
> oCommand.CommandText = sQuery
> oCommand.Properties("Page Size") = 100
> oCommand.Properties("Timeout") = 30
> oCommand.Properties("Cache Results") = False
> Set oResults = oCommand.Execute
> Do Until oResults.EOF
> if oResults.Fields("displayName") <> "" then
> sDisplayName = oResults.Fields("displayName")
> UserExists = True
> End if
> oResults.MoveNext
> Loop
> On Error Goto 0
> End Function
>
>



Re: Find user group membership by BobA

BobA
Thu Oct 12 21:54:01 CDT 2006

Richard,
Thanks alot for your help.
I have doing alot of reading on your website also.
Here is my final goal...
to check and see if the userid entered into the inputbox is a member of the
builtin administrators group
I have been trying to edit my sFilter line to include the group but Im not
sure if Im doing it right(or even if this is the correct path to be following)

input = inputbox("ID")

if UserExists(Input,sDisplayName) then
wscript.echo "User is member of the Administrators Group " & sDisplayName
else
wscript.echo "Not a member of Administrators"
end if


Function UserExists(sUser,sDisplayName)
Dim oConnection, oCommand, oRoot, sDNSDomain, sQuery, sFilter, oResults
UserExists = False
sDisplayName = sUser
On Error Resume Next
' Use ADO to search the domain for all users.
Set oConnection = CreateObject("ADODB.Connection")
Set oCommand = CreateObject("ADODB.Command")
oConnection.Provider = "ADsDSOOBject"
oConnection.Open "Active Directory Provider"
Set oCommand.ActiveConnection = oConnection
' Determine the DNS domain from the RootDSE object.
Set oRoot = GetObject("LDAP://RootDSE")
sDNSDomain = oRoot.Get("DefaultNamingContext")
'sFilter = "(&(ObjectClass=user)(ObjectCategory=person)(samAccountName=" &
sUser & "))"
sFilter =
"(&(objectClass=user)(objectCategory=person)(memberOf=CN=Administrators,CN=Builtin)(samAccountName=" & sUser & "))"
sQuery = "<LDAP://" & sDNSDomain & ">;" & sFilter &
";displayName,memberOf;subtree"
oCommand.CommandText = sQuery
oCommand.Properties("Page Size") = 100
oCommand.Properties("Timeout") = 30
oCommand.Properties("Cache Results") = False
Set oResults = oCommand.Execute

Do Until oResults.EOF
if oResults.Fields("displayName") <> "" then
sDisplayName = oResults.Fields("displayName")
UserExists = True
End if
oResults.MoveNext
Loop
On Error Goto 0
End Function

Thanks again for your help




"Richard Mueller" wrote:

> Hi,
>
> You have a few options. One is to add the memberOf attribute to the comma
> delimited list of attribute values to be retrieved by the ADO query:
>
> sQuery = "<LDAP://" & sDNSDomain & ">;" & sFilter &
> ";displayName,memberOf;subtree"
>
> The memberOf attribute is a multi-valued collection of the Distinguished
> Names of the groups the object is a direct member of (except the group
> designated as the "primary" group, which is usually "Domain Users" for
> users). You could return this collection, then loop through it and check if
> the group of interest is included. Modify Function UserExists to return
> arrGroups:
> ================
> Function UserExists(sUser, sDisplayName, arrGroups)
> .....
> sQuery = "<LDAP://" & sDNSDomain & ">;" & sFilter _
> & ";displayName,memberOf;subtree"
> .....
> Do Until oResults.EOF
> sDisplay = oResults.Fields("displayName").Value & ""
> arrGroups = oResults.Fields("memberOf").Value
> UserExists = True
> oResults.MoveNext
> Loop
> End Function
> =========
> I would recommend not using "On Error Resume Next". You can prevent an error
> raised when there is no value assigned to displayName by appending a blank
> string to the value retrieved, as above. This also means the function will
> return True even though the user has no value for this attribute. sDisplay
> will be a blank string. Then in the main part of the program:
> =========
> if UserExists(Input, sDisplayName, arrGroups) then
> wscript.echo "Found " & sDisplayName
> If IsNull(arrGroups) then
> Wscript.Echo "No group memberships"
> ElseIf (TypeName(arrGroups = "String") then
> Wscript.Echo "Member of group " & arrGroups
> Else
> For Each strGroup In arrGroups
> Wscript.Echo "Member of group " & strGroup
> Next
> End If
> else
> wscript.echo "Not account found for 'Dave'"
> end if
> =========
> Note that ADO returns memberOf as an array if there is more than one group
> DN in the collection. However, if there are no group memberships it will be
> Null, and if there is one group it will have datatype "String". You must
> account all possibilities. How you handle this depends on how many group
> memberships you want to check. You could simply check each group as they are
> enumerated, instead of echoing the names.
>
> Another approach would be to return the distinguishedName of the user in
> Function UserExists, then to check if this user is a member of a group, bind
> to the group and use the IsMember method of the group object. You pass the
> distinguishedName of the user to this method. Again, you add to the comma
> delimited list of attribute values to be retrieved by the ADO query:
>
> sQuery = "<LDAP://" & sDNSDomain & ">;" & sFilter _
> & ";displayName,distinguishedName;subtree"
>
> You would modify Function UserExists to return this value, perhaps as strDN.
> Then, to check group membership:
>
> Set objGroup = GetObject("LDAP://cn=TestGroup,ou=Sales,dc=MyDomain,dc=com")
> If (objGroup.IsMember(strDN) = True) Then
> Wscript.Echo "User is a member of the group"
> Else
> Wscript.Echo "User is NOT a member of the group"
> End If
>
> --
> Richard
> Microsoft MVP Scripting and ADSI
> Hilltop Lab - http://www.rlmueller.net
>
> "Bob A" <BobA@discussions.microsoft.com> wrote in message
> news:76EE2F97-5843-4621-8DF4-37D9A3339F77@microsoft.com...
> >I am using this script to check to see if a user exists in AD. Since there
> >is
> > already a connection to AD would it be possible to check for group
> > membership
> > at the same time??...and if so..how?
> >
> > Thanks
> >
> > input = inputbox("Enter UserID")
> >
> > if UserExists(Input,sDisplayName) then
> > wscript.echo "Found " & sDisplayName
> > else
> > wscript.echo "Not account found for 'Dave'"
> > end if
> >
> >
> > Function UserExists(sUser,sDisplayName)
> > Dim oConnection, oCommand, oRoot, sDNSDomain, sQuery, sFilter, oResults
> > UserExists = False
> > sDisplayName = sUser
> > On Error Resume Next
> > ' Use ADO to search the domain for all users.
> > Set oConnection = CreateObject("ADODB.Connection")
> > Set oCommand = CreateObject("ADODB.Command")
> > oConnection.Provider = "ADsDSOOBject"
> > oConnection.Open "Active Directory Provider"
> > Set oCommand.ActiveConnection = oConnection
> > ' Determine the DNS domain from the RootDSE object.
> > Set oRoot = GetObject("LDAP://RootDSE")
> > sDNSDomain = oRoot.Get("DefaultNamingContext")
> > sFilter = "(&(ObjectClass=user)(ObjectCategory=person)(samAccountName=" &
> > sUser & "))"
> > sQuery = "<LDAP://" & sDNSDomain & ">;" & sFilter &
> > ";displayName;subtree"
> > oCommand.CommandText = sQuery
> > oCommand.Properties("Page Size") = 100
> > oCommand.Properties("Timeout") = 30
> > oCommand.Properties("Cache Results") = False
> > Set oResults = oCommand.Execute
> > Do Until oResults.EOF
> > if oResults.Fields("displayName") <> "" then
> > sDisplayName = oResults.Fields("displayName")
> > UserExists = True
> > End if
> > oResults.MoveNext
> > Loop
> > On Error Goto 0
> > End Function
> >
> >
>
>
>

Re: Find user group membership by BobA

BobA
Thu Oct 12 21:58:02 CDT 2006

Richard,
Thanks alot for your help.
Here is my final goal...
To check if the userid entered into the input box is valid and a member of
the builtin administrators group. I have been editing the sFilter to try and
grab just members of the group but I dont think Im doing it right (or if this
is even the correct way)
Here is the code:

input = inputbox("ID")
if UserExists(Input,sDisplayName) then
wscript.echo "User is member of the Administrators Group " & sDisplayName
else
wscript.echo "Not a member of Administrators"
end if
Function UserExists(sUser,sDisplayName)
Dim oConnection, oCommand, oRoot, sDNSDomain, sQuery, sFilter, oResults
UserExists = False
sDisplayName = sUser
On Error Resume Next
' Use ADO to search the domain for all users.
Set oConnection = CreateObject("ADODB.Connection")
Set oCommand = CreateObject("ADODB.Command")
oConnection.Provider = "ADsDSOOBject"
oConnection.Open "Active Directory Provider"
Set oCommand.ActiveConnection = oConnection
' Determine the DNS domain from the RootDSE object.
Set oRoot = GetObject("LDAP://RootDSE")
sDNSDomain = oRoot.Get("DefaultNamingContext")
'sFilter = "(&(ObjectClass=user)(ObjectCategory=person)(samAccountName=" &
sUser & "))"
sFilter =
"(&(objectClass=user)(objectCategory=person)(memberOf=CN=Administrators,CN=Builtin)(samAccountName=" & sUser & "))"
sQuery = "<LDAP://" & sDNSDomain & ">;" & sFilter &
";displayName,memberOf;subtree"
oCommand.CommandText = sQuery
oCommand.Properties("Page Size") = 100
oCommand.Properties("Timeout") = 30
oCommand.Properties("Cache Results") = False
Set oResults = oCommand.Execute
Do Until oResults.EOF
if oResults.Fields("displayName") <> "" then
sDisplayName = oResults.Fields("displayName")
UserExists = True
End if
oResults.MoveNext
Loop
On Error Goto 0
End Function

Thanks Alot for your help!

Bob

"Richard Mueller" wrote:

> Hi,
>
> You have a few options. One is to add the memberOf attribute to the comma
> delimited list of attribute values to be retrieved by the ADO query:
>
> sQuery = "<LDAP://" & sDNSDomain & ">;" & sFilter &
> ";displayName,memberOf;subtree"
>
> The memberOf attribute is a multi-valued collection of the Distinguished
> Names of the groups the object is a direct member of (except the group
> designated as the "primary" group, which is usually "Domain Users" for
> users). You could return this collection, then loop through it and check if
> the group of interest is included. Modify Function UserExists to return
> arrGroups:
> ================
> Function UserExists(sUser, sDisplayName, arrGroups)
> .....
> sQuery = "<LDAP://" & sDNSDomain & ">;" & sFilter _
> & ";displayName,memberOf;subtree"
> .....
> Do Until oResults.EOF
> sDisplay = oResults.Fields("displayName").Value & ""
> arrGroups = oResults.Fields("memberOf").Value
> UserExists = True
> oResults.MoveNext
> Loop
> End Function
> =========
> I would recommend not using "On Error Resume Next". You can prevent an error
> raised when there is no value assigned to displayName by appending a blank
> string to the value retrieved, as above. This also means the function will
> return True even though the user has no value for this attribute. sDisplay
> will be a blank string. Then in the main part of the program:
> =========
> if UserExists(Input, sDisplayName, arrGroups) then
> wscript.echo "Found " & sDisplayName
> If IsNull(arrGroups) then
> Wscript.Echo "No group memberships"
> ElseIf (TypeName(arrGroups = "String") then
> Wscript.Echo "Member of group " & arrGroups
> Else
> For Each strGroup In arrGroups
> Wscript.Echo "Member of group " & strGroup
> Next
> End If
> else
> wscript.echo "Not account found for 'Dave'"
> end if
> =========
> Note that ADO returns memberOf as an array if there is more than one group
> DN in the collection. However, if there are no group memberships it will be
> Null, and if there is one group it will have datatype "String". You must
> account all possibilities. How you handle this depends on how many group
> memberships you want to check. You could simply check each group as they are
> enumerated, instead of echoing the names.
>
> Another approach would be to return the distinguishedName of the user in
> Function UserExists, then to check if this user is a member of a group, bind
> to the group and use the IsMember method of the group object. You pass the
> distinguishedName of the user to this method. Again, you add to the comma
> delimited list of attribute values to be retrieved by the ADO query:
>
> sQuery = "<LDAP://" & sDNSDomain & ">;" & sFilter _
> & ";displayName,distinguishedName;subtree"
>
> You would modify Function UserExists to return this value, perhaps as strDN.
> Then, to check group membership:
>
> Set objGroup = GetObject("LDAP://cn=TestGroup,ou=Sales,dc=MyDomain,dc=com")
> If (objGroup.IsMember(strDN) = True) Then
> Wscript.Echo "User is a member of the group"
> Else
> Wscript.Echo "User is NOT a member of the group"
> End If
>
> --
> Richard
> Microsoft MVP Scripting and ADSI
> Hilltop Lab - http://www.rlmueller.net
>
> "Bob A" <BobA@discussions.microsoft.com> wrote in message
> news:76EE2F97-5843-4621-8DF4-37D9A3339F77@microsoft.com...
> >I am using this script to check to see if a user exists in AD. Since there
> >is
> > already a connection to AD would it be possible to check for group
> > membership
> > at the same time??...and if so..how?
> >
> > Thanks
> >
> > input = inputbox("Enter UserID")
> >
> > if UserExists(Input,sDisplayName) then
> > wscript.echo "Found " & sDisplayName
> > else
> > wscript.echo "Not account found for 'Dave'"
> > end if
> >
> >
> > Function UserExists(sUser,sDisplayName)
> > Dim oConnection, oCommand, oRoot, sDNSDomain, sQuery, sFilter, oResults
> > UserExists = False
> > sDisplayName = sUser
> > On Error Resume Next
> > ' Use ADO to search the domain for all users.
> > Set oConnection = CreateObject("ADODB.Connection")
> > Set oCommand = CreateObject("ADODB.Command")
> > oConnection.Provider = "ADsDSOOBject"
> > oConnection.Open "Active Directory Provider"
> > Set oCommand.ActiveConnection = oConnection
> > ' Determine the DNS domain from the RootDSE object.
> > Set oRoot = GetObject("LDAP://RootDSE")
> > sDNSDomain = oRoot.Get("DefaultNamingContext")
> > sFilter = "(&(ObjectClass=user)(ObjectCategory=person)(samAccountName=" &
> > sUser & "))"
> > sQuery = "<LDAP://" & sDNSDomain & ">;" & sFilter &
> > ";displayName;subtree"
> > oCommand.CommandText = sQuery
> > oCommand.Properties("Page Size") = 100
> > oCommand.Properties("Timeout") = 30
> > oCommand.Properties("Cache Results") = False
> > Set oResults = oCommand.Execute
> > Do Until oResults.EOF
> > if oResults.Fields("displayName") <> "" then
> > sDisplayName = oResults.Fields("displayName")
> > UserExists = True
> > End if
> > oResults.MoveNext
> > Loop
> > On Error Goto 0
> > End Function
> >
> >
>
>
>

Re: Find user group membership by BobA

BobA
Fri Oct 13 08:05:02 CDT 2006

Richard,
Here is the code I modified per your suggestions. It will not return the
groups.

input = inputbox("ID")

On Error Resume Next

if UserExists(Input, sDisplayName, arrGroups) then
wscript.echo "Found " & sDisplayName
If IsNull(arrGroups) then
Wscript.Echo "No group memberships"
ElseIf (TypeName (arrGroups = "Administrators")) then
Wscript.Echo "Member of group " & arrGroups
Else
For Each strGroup In arrGroups
Wscript.Echo "Member of group " & strGroup
Next
End If
else
wscript.echo "Not valid account"
end if


'if UserExists(Input,sDisplayName) then
' wscript.echo "User is member of the Administrators Group " & sDisplayName
'else
' wscript.echo "Not a member of Administrators"
'end if


Function UserExists(sUser,sDisplayName, arrGroups)
Dim oConnection, oCommand, oRoot, sDNSDomain, sQuery, sFilter, oResults
UserExists = False
sDisplayName = sUser
On Error Resume Next
' Use ADO to search the domain for all users.
Set oConnection = CreateObject("ADODB.Connection")
Set oCommand = CreateObject("ADODB.Command")
oConnection.Provider = "ADsDSOOBject"
oConnection.Open "Active Directory Provider"
Set oCommand.ActiveConnection = oConnection
' Determine the DNS domain from the RootDSE object.
Set oRoot = GetObject("LDAP://RootDSE")
sDNSDomain = oRoot.Get("DefaultNamingContext")
sFilter = "(&(ObjectClass=user)(ObjectCategory=person)(samAccountName=" &
sUser & "))"
'sFilter =
"(&(objectClass=user)(objectCategory=person)(memberOf=CN=Administrators,CN=Builtin)(samAccountName=" & sUser & "))"
sQuery = "<LDAP://" & sDNSDomain & ">;" & sFilter &
";displayName,memberOf;subtree"
oCommand.CommandText = sQuery
oCommand.Properties("Page Size") = 100
oCommand.Properties("Timeout") = 30
oCommand.Properties("Cache Results") = False
Set oResults = oCommand.Execute



'Do Until oResults.EOF
' if oResults.Fields("displayName") <> "" then
' sDisplayName = oResults.Fields("displayName")
' UserExists = True
' End if
' oResults.MoveNext
'Loop
'On Error Goto 0
'End Function

Do Until oResults.EOF
sDisplay = oResults.Fields("displayName").Value & ""
arrGroups = oResults.Fields("memberOf").Value
UserExists = True
oResults.MoveNext
Loop
End Function



"Bob A" wrote:

> Richard,
> Thanks alot for your help.
> Here is my final goal...
> To check if the userid entered into the input box is valid and a member of
> the builtin administrators group. I have been editing the sFilter to try and
> grab just members of the group but I dont think Im doing it right (or if this
> is even the correct way)
> Here is the code:
>
> input = inputbox("ID")
> if UserExists(Input,sDisplayName) then
> wscript.echo "User is member of the Administrators Group " & sDisplayName
> else
> wscript.echo "Not a member of Administrators"
> end if
> Function UserExists(sUser,sDisplayName)
> Dim oConnection, oCommand, oRoot, sDNSDomain, sQuery, sFilter, oResults
> UserExists = False
> sDisplayName = sUser
> On Error Resume Next
> ' Use ADO to search the domain for all users.
> Set oConnection = CreateObject("ADODB.Connection")
> Set oCommand = CreateObject("ADODB.Command")
> oConnection.Provider = "ADsDSOOBject"
> oConnection.Open "Active Directory Provider"
> Set oCommand.ActiveConnection = oConnection
> ' Determine the DNS domain from the RootDSE object.
> Set oRoot = GetObject("LDAP://RootDSE")
> sDNSDomain = oRoot.Get("DefaultNamingContext")
> 'sFilter = "(&(ObjectClass=user)(ObjectCategory=person)(samAccountName=" &
> sUser & "))"
> sFilter =
> "(&(objectClass=user)(objectCategory=person)(memberOf=CN=Administrators,CN=Builtin)(samAccountName=" & sUser & "))"
> sQuery = "<LDAP://" & sDNSDomain & ">;" & sFilter &
> ";displayName,memberOf;subtree"
> oCommand.CommandText = sQuery
> oCommand.Properties("Page Size") = 100
> oCommand.Properties("Timeout") = 30
> oCommand.Properties("Cache Results") = False
> Set oResults = oCommand.Execute
> Do Until oResults.EOF
> if oResults.Fields("displayName") <> "" then
> sDisplayName = oResults.Fields("displayName")
> UserExists = True
> End if
> oResults.MoveNext
> Loop
> On Error Goto 0
> End Function
>
> Thanks Alot for your help!
>
> Bob
>
> "Richard Mueller" wrote:
>
> > Hi,
> >
> > You have a few options. One is to add the memberOf attribute to the comma
> > delimited list of attribute values to be retrieved by the ADO query:
> >
> > sQuery = "<LDAP://" & sDNSDomain & ">;" & sFilter &
> > ";displayName,memberOf;subtree"
> >
> > The memberOf attribute is a multi-valued collection of the Distinguished
> > Names of the groups the object is a direct member of (except the group
> > designated as the "primary" group, which is usually "Domain Users" for
> > users). You could return this collection, then loop through it and check if
> > the group of interest is included. Modify Function UserExists to return
> > arrGroups:
> > ================
> > Function UserExists(sUser, sDisplayName, arrGroups)
> > .....
> > sQuery = "<LDAP://" & sDNSDomain & ">;" & sFilter _
> > & ";displayName,memberOf;subtree"
> > .....
> > Do Until oResults.EOF
> > sDisplay = oResults.Fields("displayName").Value & ""
> > arrGroups = oResults.Fields("memberOf").Value
> > UserExists = True
> > oResults.MoveNext
> > Loop
> > End Function
> > =========
> > I would recommend not using "On Error Resume Next". You can prevent an error
> > raised when there is no value assigned to displayName by appending a blank
> > string to the value retrieved, as above. This also means the function will
> > return True even though the user has no value for this attribute. sDisplay
> > will be a blank string. Then in the main part of the program:
> > =========
> > if UserExists(Input, sDisplayName, arrGroups) then
> > wscript.echo "Found " & sDisplayName
> > If IsNull(arrGroups) then
> > Wscript.Echo "No group memberships"
> > ElseIf (TypeName(arrGroups = "String") then
> > Wscript.Echo "Member of group " & arrGroups
> > Else
> > For Each strGroup In arrGroups
> > Wscript.Echo "Member of group " & strGroup
> > Next
> > End If
> > else
> > wscript.echo "Not account found for 'Dave'"
> > end if
> > =========
> > Note that ADO returns memberOf as an array if there is more than one group
> > DN in the collection. However, if there are no group memberships it will be
> > Null, and if there is one group it will have datatype "String". You must
> > account all possibilities. How you handle this depends on how many group
> > memberships you want to check. You could simply check each group as they are
> > enumerated, instead of echoing the names.
> >
> > Another approach would be to return the distinguishedName of the user in
> > Function UserExists, then to check if this user is a member of a group, bind
> > to the group and use the IsMember method of the group object. You pass the
> > distinguishedName of the user to this method. Again, you add to the comma
> > delimited list of attribute values to be retrieved by the ADO query:
> >
> > sQuery = "<LDAP://" & sDNSDomain & ">;" & sFilter _
> > & ";displayName,distinguishedName;subtree"
> >
> > You would modify Function UserExists to return this value, perhaps as strDN.
> > Then, to check group membership:
> >
> > Set objGroup = GetObject("LDAP://cn=TestGroup,ou=Sales,dc=MyDomain,dc=com")
> > If (objGroup.IsMember(strDN) = True) Then
> > Wscript.Echo "User is a member of the group"
> > Else
> > Wscript.Echo "User is NOT a member of the group"
> > End If
> >
> > --
> > Richard
> > Microsoft MVP Scripting and ADSI
> > Hilltop Lab - http://www.rlmueller.net
> >
> > "Bob A" <BobA@discussions.microsoft.com> wrote in message
> > news:76EE2F97-5843-4621-8DF4-37D9A3339F77@microsoft.com...
> > >I am using this script to check to see if a user exists in AD. Since there
> > >is
> > > already a connection to AD would it be possible to check for group
> > > membership
> > > at the same time??...and if so..how?
> > >
> > > Thanks
> > >
> > > input = inputbox("Enter UserID")
> > >
> > > if UserExists(Input,sDisplayName) then
> > > wscript.echo "Found " & sDisplayName
> > > else
> > > wscript.echo "Not account found for 'Dave'"
> > > end if
> > >
> > >
> > > Function UserExists(sUser,sDisplayName)
> > > Dim oConnection, oCommand, oRoot, sDNSDomain, sQuery, sFilter, oResults
> > > UserExists = False
> > > sDisplayName = sUser
> > > On Error Resume Next
> > > ' Use ADO to search the domain for all users.
> > > Set oConnection = CreateObject("ADODB.Connection")
> > > Set oCommand = CreateObject("ADODB.Command")
> > > oConnection.Provider = "ADsDSOOBject"
> > > oConnection.Open "Active Directory Provider"
> > > Set oCommand.ActiveConnection = oConnection
> > > ' Determine the DNS domain from the RootDSE object.
> > > Set oRoot = GetObject("LDAP://RootDSE")
> > > sDNSDomain = oRoot.Get("DefaultNamingContext")
> > > sFilter = "(&(ObjectClass=user)(ObjectCategory=person)(samAccountName=" &
> > > sUser & "))"
> > > sQuery = "<LDAP://" & sDNSDomain & ">;" & sFilter &
> > > ";displayName;subtree"
> > > oCommand.CommandText = sQuery
> > > oCommand.Properties("Page Size") = 100
> > > oCommand.Properties("Timeout") = 30
> > > oCommand.Properties("Cache Results") = False
> > > Set oResults = oCommand.Execute
> > > Do Until oResults.EOF
> > > if oResults.Fields("displayName") <> "" then
> > > sDisplayName = oResults.Fields("displayName")
> > > UserExists = True
> > > End if
> > > oResults.MoveNext
> > > Loop
> > > On Error Goto 0
> > > End Function
> > >
> > >
> >
> >
> >

Re: Find user group membership by Richard

Richard
Fri Oct 13 12:12:28 CDT 2006

Bob,

The approach you are taking is not efficient, and I suspect it will not meet
your needs. Rather than searching all of AD for the user, it is more
efficient to use the NameTranslate object. This converts the NT name of the
user (the value of the sAMAccountName attribute) to the Distinguished Name.
It also quickly raises an error if the user object does not exist.

Also, if you retrieve the memberOf attribute of the user, this only includes
groups the user is a direct member of. It does not account for group
nesting. If you need to know if the user has Administrative privileges, this
is important. For example, the user could be a direct member of the "Domain
Admins" group, which is usually a member of the Built-in Administrators
group. The memberOf attribute would not reveal the user is a member of the
Built-in Administrators group, even though they would have all privileges
assigned to that group. A better approach is to use the tokenGroups
attribute of the user. This is a collection of group SID values. Sids are
byte arrays, so they take special coding to handle. However, the tokenGroups
collection includes the SID's for all groups the user is a member of,
including any memberships due to group nesting. It also includes the
"primary" group of the user. This membership is not included in the memberOf
collection. The only group memberships not revealed by tokenGroups are
cross-domain memberships (groups in other domains).

The program below prompts for a user name (the NT name, or "pre-Windows 2000
logon name"). It uses the NameTranslate object to convert this to the
Distinguished Name (DN). It also retrieves the DNS name of the domain from
the RootDSE object, then uses NameTranslate to convert this to the NetBIOS
name of the domain, which is needed to convert the NT name of the user to
the DN. If the user does not exist, we trap that error and alert the user.
With the DN we can bind to the user object. I use a function called IsAdmin
to check if the user is a member of the Built-in Administrators group. This
function binds to the built-in group and retrieves the value of the
objectSid attribute, which is the SID of the group, and converts this byte
array to a string. Next the function enumerates the tokenGroups collection
of the user, converts each to a SID string, and compares to the SID of the
Built-in Administrators group. This reliably determines if the user is a
member of the built-in group. In fact, this program can be used to determine
if any AD object is a member of the Built-in Administrators group. For
example, it reveals that the "Domain Admins" group is a member in my domain.
I ran the program and entered "Domain Admins" for the user name. Here is the
program:
=========
Option Explicit

Dim objRootDSE, strDNSDomain, objTrans, strNetBIOSDomain
Dim strUser, strUserDN, objUser

' Constants for the NameTranslate object.
Const ADS_NAME_INITTYPE_GC = 3
Const ADS_NAME_TYPE_NT4 = 3
Const ADS_NAME_TYPE_1779 = 1

strUser = InputBox("Enter User Name", "Check Admin")

' Determine DNS name of domain from RootDSE.
Set objRootDSE = GetObject("LDAP://RootDSE")
strDNSDomain = objRootDSE.Get("defaultNamingContext")

' Use the NameTranslate object to find the NetBIOS
' domain name from the DNS domain name.
Set objTrans = CreateObject("NameTranslate")
objTrans.Init ADS_NAME_INITTYPE_GC, ""
objTrans.Set ADS_NAME_TYPE_1779, strDNSDomain
strNetBIOSDomain = objTrans.Get(ADS_NAME_TYPE_NT4)

' Remove trailing backslash.
strNetBIOSDomain = Left(strNetBIOSDomain, _
Len(strNetBIOSDomain) - 1)

' Use the NameTranslate object to convert user NT Name
' to Distinguished Names.
' Trap error if object does not exist in AD.
On Error Resume Next
objTrans.Set ADS_NAME_TYPE_NT4, strNetBIOSDomain & "\" & strUser
If (Err.Number <> 0) Then
On Error GoTo 0
Wscript.Echo "User " & strUser & " not found"
Wscript.Quit
End If
On Error GoTo 0
strUserDN = objTrans.Get(ADS_NAME_TYPE_1779)

' Bind to the user object.
Set objUser = GetObject("LDAP://" & strUserDN)

' Check if the user is a member of the Built-in Administrators group.
If (IsAdmin(objUser, strDNSDomain) = True) Then
Wscript.Echo "User is a member of Built-in Administrators group"
Else
Wscript.Echo "User is NOT a member of Built-in Administrators group"
End If

Function IsAdmin(objUser, strDNSDomain)
' Function returns True if objUser is a member of the
' builtin Administrators group, False otherwise.

Dim objAdminGroup, arrbytSid, strAdmGrpSid, arrbytGroups
Dim strGroupSid, j

' Bind to the Built-in Administrators group.
' This group must be in the Built-in container.
Set objAdminGroup = GetObject("LDAP://cn=Administrators,cn=Builtin," _
& strDNSDomain)

' Retrieve the SID of the Built-in Administrators group.
arrbytSid = objAdminGroup.objectSid
strAdmGrpSid = OctetToHexStr(arrbytSid)

' Retrieve SID's of all groups the user is a member of.
' This collection includes membership due to group nesting,
' and the "primary" group of the user.
objUser.GetInfoEx Array("tokenGroups"), 0
arrbytGroups = objUser.Get("tokenGroups")

' Check if any of these group SID values match the
' Built-in Administartor group.
If (UBound(arrbytGroups) = -1) Then
' There are not Sids in the collection.
' This can only happen if objUser is a group.
IsAdmin = False
Exit Function
End If
If (TypeName(arrbytGroups) = "Byte()") Then
' There is only one SID value in the collection.
strGroupSid = OctetToHexStr(arrbytGroups)
If (strAdmGrpSid = strGroupSid) Then
IsAdmin = True
Else
IsAdmin = False
End If
Exit Function
End If
' There is more than one SID value in the collection.
' Check each one.
For j = 0 To UBound(arrbytGroups)
strGroupSId = OctetToHexStr(arrbytGroups(j))
If (strAdmGrpSid = strGroupSid) Then
IsAdmin = True
Exit Function
End If
Next
' None of the SID values matched. The user is not a member
' of the Built-in Administrators group.
IsAdmin = False
Exit Function
End Function

Function OctetToHexStr(arrbytOctet)
' Function to convert OctetString (byte array) to Hex string.

Dim k

OctetToHexStr = ""
For k = 1 To Lenb(arrbytOctet)
OctetToHexStr = OctetToHexStr _
& Right("0" & Hex(Ascb(Midb(arrbytOctet, k, 1))), 2)
Next
End Function
--
Richard
Microsoft MVP Scripting and ADSI
Hilltop Lab - http://www.rlmueller.net