Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

ADSI scripting help - Domain Users group not readable?

Status
Not open for further replies.

jonheese

Programmer
Oct 7, 2005
41
US
I'm writing a quick VBScript using the ADSI scripting stuff that is designed to loop through the members of "Domain Users", adding each one to a second group (long story).

I'm running into some trouble with it though, and I think it may have to do with the security permissions/ACLs on the Domain Users group itself...

Here's a quick snippet of my VB code:

=== BEGIN CODE SNIPPET ===
Const ADS_PROPERTY_APPEND = 3

Set objRootDSE = GetObject("LDAP://rootDSE")
Set objGroup = GetObject("LDAP://cn=Domain Users,cn=Users," & objRootDSE.Get("defaultNamingContext"))
objGroup.GetInfo

arrMemberOf = objGroup.GetEx("member")

=== END CODE SNIPPET ===

It gets to the last line in the snippet and throws "Error: The directory property cannot be found in the cache, Code: 8000500D".

At first I thought that it may have been a typo or something, but when I change "Domain Users" in the GetObject line to another group in the "Users" CN, it gets past the "GetEx" line without a problem and works perfectly (yes, there's more code past the snippet that I didn't include).

So, I'm suspecting that there is a security issue with the Domain Users group. I'm running the script as the domain Administrator, and opening ADUC as that user enables me to play with Domain Users with no problem.

Any ideas how to continue troubleshooting this?

Regards,
Jon Heese
 
Try something like this:

Code:
Set objRootDSE = GetObject("LDAP://rootDSE")
Set objItem = GetObject("LDAP://cn=Domain Users,cn=Users," & _
           objRootDSE.Get("defaultNamingContext"))
For Each objUser in objItem.Members
   Wscript.Echo objUser.Name & vbCrLf
Next
 
Interesting suggestion. :)

First, I'm assuming that you meant "objGroup", not "objItem" (which isn't declared anywhere else in your suggestion).

With that correction: Nope. No error, just silent exit.

I'm guessing that the objGroup.Members array (?) is empty. Got a quick way to check its size? I tried .size() and .length(), but those both failed with "Object doesn't support this property or method" errors...

Also, I should point out that I built my script from an example script on Microsoft's site, here:

[URL unfurl="true"]http://www.microsoft.com/technet/scriptcenter/scripts/ad/groups/adgpvb13.mspx[/url]

Regards,
Jon Heese
 
First, I'm assuming that you meant "objGroup", not "objItem" (which isn't declared anywhere else in your suggestion).

objItem, objGroup, since the object is being declared when it's first being used either will work as long as you're consistent when you address them.

My next suggestion would be to try making a string out of "cn=Domain Users,cn=Users," & objRootDSE.Get("defaultNamingContext")", like:

Code:
strDN = "cn=Domain Users,cn=Users," & objRootDSE.Get("defaultNamingContext")

Then do a Wscript.Echo strDN to make sure that the string is formed correctly. Then instead of doing:

Code:
Set objItem = GetObject("LDAP://cn=Domain Users,cn=Users," & _
           objRootDSE.Get("defaultNamingContext"))

Do a:

Code:
Set objItem = GetObject("LDAP://" & strDN)

That's the way that I usually do it.
 
objItem, objGroup, since the object is being declared when it's first being used either will work as long as you're consistent when you address them.

Right, I should have been clearer, but I was referencing the "for each" line, since that's where your original suggested script puked. Bygones.

My next suggestion would be to try making a string out of "cn=Domain Users,cn=Users," & objRootDSE.Get("defaultNamingContext")"...

Actually, I'm very sure that this will make no difference. Did you read the part in my original post where I described how I changed the group name to another group (besides Domain Users), and it worked fine? I first suspected that the whitespace in the middle of the group name was the problem, but another group name with a space in it still works perfectly...

This is almost certainly NOT a VBScript issue, but rather an Active Directory permission/ACL issue (that's why I posted it here instead of in the VBScript forum :)). As further evidence of this fact, one of the reasons that I need to do a regular wholesale copy of users from the Domain Users group to another group is because of an issue where trying to expand the Domain Users group in Outlook's "To:" field yields a permissions-y error.

So once again: Is there a field or method in the ".Members" object that I can reference to test length?

I'd look it up myself, but I don't know what kind of object you're expecting .Members to yield (array? set? etc.?).

Also, if anyone has any ideas for troubleshooting/checking permissions/ACL on the actual AD group object, I'd really appreciate hearing about it.

Thanks again for all your help.

Regards,
Jon Heese
 
Woops, I just looked back at your original suggestion, and I missed that you did originally declare the group object as objItem... I replaced that line in your suggestion with mine, since it was already there, and I didn't notice the different variable names until the script complained.

I thought it was your mistake, but I see now it was mine. ::blush::

And now back to your ordinary programming... :)

Regards,
Jon Heese
 
That's OK. I'm pretty sure that it returns an array. If you assign the results to a variable like strResults and then do a VarType(strResults) it will respond with a code. I believe 8204 is what you should get, which is an array of variants.

If there's a permissions issue, have you tried the obvious (like checking the Security tab)? Maybe if you look at the object in ADSIEdit you'll see something that sticks out.

I'll be honest, I've never done scripting with Domain Users, but I have with lots of other AD functions and objects. The one thing that is constant is that things don't always seem to work the way that you would a) expect them to and b) have experienced them in the past.
 
Ah yes, I didn't have "Advanced Features" checkmark on in ADUC, so I couldn't see the Security tab on the group objects...

I just turned it on, and compared its security settings with another group that's working fine, both with the script and in Outlook... no differences. And I verified that Domain Admins group (to which the domain Administrator belongs) is given full control.

The thing is, I'm able to modify the group just fine in ADUC snap-in as Administrator; It's just the script and the Outlook name resolution features that seem to not work.

I'll take a peek in ADSIEdit, but I've only played with that a bit, so I'm not sure I'd even know what I was looking at if I did find the problem. :)

Any other ideas?

Thanks again.

Regards,
Jon Heese
 
Aha...

I was just looking through the properties of "Domain Users" in ADSIEdit, and I noticed that the "member" property is listed as "<Not Set>" (i.e. empty), whereas that same property of other groups contains the explicit list of group members...

I checked this against a couple other 2003 servers and found the exact same thing everywhere.

So, it looks like the Domain Users group handles/stores its members in a different way than other groups. My first guess was that since all domain users are automatically added to the Domain Users group, that membership is compulsory, so it doesn't need to keep a list of members.

But, upon further examination, that doesn't really make sense. After all, it is possible to remove a user from the Domain Users group (after changing their primary group, if necessary). There must be someplace that keeps track of the members explicitly...

Anyone know if this is a bug, or intended behavior? I can find no mention of any distinction between the Domain Users group and other groups on TechNet or any of MS's sites.

Regards,
Jon Heese
 
hi

i've observed today a wrong behaviour like this:
(sorry for my English language :) )

i'm trying to prepare a web-page to manage domain users, and it seems to be working but:
1 - i receive Active Directory error '8000500d' when i try to read a 'not set' property (in my case homeDirectory or memberOf
2 - i'm not to be able to write memberOf property with
us.PutEx 2, "memberOf", Array("CN=hcprot,CN=Users,DC=upo,DC=local") ===> error '80072035'
3 - then i can't find the user (which i can create successfully) because i use these instruction for query in names and usernames

SELECT givenName,sn,userPrincipalName,physicalDeliveryOfficeName,distinguishedName,userAccountControl FROM 'LDAP://CN=Users,DC=upo,DC=local' WHERE objectClass = 'user' AND memberOf = 'CN=hcprot,CN=Users,DC=upo,DC=local' AND userPrincipalName = '*[..]*'

I can add the user to hcprot group with
objGroup.Add("LDAP://CN=" & cn & ",CN=Users,DC=upo,DC=local")
but this does not add a value in user memberOf property, while working in ADUC does (note that in ADUC i see that the created user is really a member of hcprot

i'm crying.. :)
 
That group's membership is dynamically queried and not static by design.

You can do what you are looking for like this:

Code:
'==========================================================================
'
' NAME: ListUsers.vbs
'
' AUTHOR: Mark D. MacLachlan , The Spider's Parlor
' URL: [URL unfurl="true"]http://www.thespidersparlor.com[/URL]
' DATE  : 12/4/2007
' COPYRIGHT (c) 2007 All Rights Reserved
'
' COMMENT: 
'
'    THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
'    ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
'    THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
'    PARTICULAR PURPOSE.
'
'    IN NO EVENT SHALL THE SPIDER'S PARLOR AND/OR ITS RESPECTIVE SUPPLIERS 
'    BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
'    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
'    WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
'    ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
'    OF THIS CODE OR INFORMATION.
'
'==========================================================================
On Error Resume Next

Dim qQuery, objConnection, objCommand, objRecordSet, obj
Dim oRootDSE, strDomain, objGroup

Set oRootDSE = GetObject("LDAP://rootDSE")
strDomain = oRootDSE.get("defaultNamingContext")

' other categories = computer, user, printqueue, group
qQuery = "<LDAP://" & strDomain &">;" & _
		"(objectCategory=person)" & _
       ";name,distinguishedName;subtree"

Set objConnection = CreateObject("ADODB.Connection")
Set objCommand = CreateObject("ADODB.Command")
objConnection.Open "Provider=ADsDSOObject;"
objCommand.ActiveConnection = objConnection
objCommand.CommandText = qQuery
Set objRecordSet = objCommand.Execute
Set objGroup = GetObject("LDAP://CN=Managers,OU=Employees," & strDomain)


While Not objRecordSet.EOF
    strUser = objRecordSet.Fields("distinguishedName")
    objGroup.put "member", (strUser)
    objrecordset.MoveNext
Wend

objConnection.Close[/close]

I hope you find this post helpful.  

Regards,

Mark

Check out my scripting solutions at [URL unfurl="true"]http://www.thespidersparlor.com/vbscript[/URL]

Work SMARTER not HARDER.  The Spider's Parlor's Admin Script Pack is a collection of Administrative scripts designed to make IT Administration easier!  Save time, get more work done, get the Admin Script Pack.
 
sorry but i don't understand your script:
- you obtain all users
- you put all of them in a group

is it right?

you think that

objGroup.put "member", (strUser)

works as manual operation in AUDC?

 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top