system.directoryservices - directoryentry.children

J

Joe User

Need ideas - have app that retrieves user and group info from ADSI WinNT
provider via .Net system.directoryservices. What I have run into is an
issue where the .Net call to retrieve the children of the domain works great
(where I can retrieve users and groups), but in attempting to ID group
members - where I retrieve the group object first - the group object's
children property fails with an exception - yet a native invocation of the
ADSI group object's members method works great. This complicates other
actions I wanted to implement later - and it would seem that the children
property should work as well as the native call. Any ideas ?

-J
 
M

Marc Scheuner [MVP ADSI]

Need ideas - have app that retrieves user and group info from ADSI WinNT
provider via .Net system.directoryservices. What I have run into is an
issue where the .Net call to retrieve the children of the domain works great
(where I can retrieve users and groups), but in attempting to ID group
members - where I retrieve the group object first - the group object's
children property fails with an exception

Group membership is *NOT* modelled through the .Children property!

In order to get all the members of a group, you need to inspect the
"member" property (if you're using the LDAP provider - which is
STRONGLY recommended over WinNT), or you need to invoke the ".Members"
function on the IADsGroup interface.

Marc
================================================================
Marc Scheuner May The Source Be With You!
Berne, Switzerland m.scheuner -at- inova.ch
 
J

Joe User

Well - that explains why it hasn't worked! Is there somewhere that this is
documented ? To be more specific - it would appear from the intent of the
class that this is exactly what the .children property was intended to
support. In fact I am pretty sure I've run into an example using it in just
this way for a different ADSI provider. That said, however, I don't doubt
that for the WinNT provider it may just not work. WRT .Members, I've got
working code to invoke the call to .Members - but this approach just
complicates anything else I would want to do with the objects in the
directory - and kind of defeats the purpose of this class - making .Net less
attractive than other options. Suggestions (within reason) ?

- J
 
M

Marc Scheuner [MVP ADSI]

Well - that explains why it hasn't worked! Is there somewhere that this is
documented ? To be more specific - it would appear from the intent of the
class that this is exactly what the .children property was intended to
support.

No, that assumption would be wrong. Being part of an OU, and member of
a group, are two fundamentally different things - hence the different
ways of modelling them.

Any user can be inside only one given OU at any time - he has to be in
a container of sorts (OU, or generic container) at all times. But as I
said - you can never be inside more than a single container.

Group membership is very different - you can be associated with any
number of groups - you're not physically *IN* that group - you just
belong to it.

It's like in the real world - you can physically only be in one given
room or building at any given point in time, but you can be member of
many groups (professional organisation, sports club, what have you)
simultaneously.
WRT .Members, I've got
working code to invoke the call to .Members - but this approach just
complicates anything else I would want to do with the objects in the
directory - and kind of defeats the purpose of this class - making .Net less
attractive than other options.

Too bad - but that's the way it is. If you use the LDAP provider
(rather than the OBSOLETE, supported-only-for-backwards-compatibility
WinNT provider); using .NET (C#, VB.NET) is in fact a LOT easier than
going by the straight old-style ADSI interfaces.....

(a) Get all objects inside an OU:

DirectoryEntry deOU = new
DirectoryEntry("LDAP://ou=MyOU,dc=fabrikam,dc=com");

foreach(DirectoryEntry deChild in deOU.Children)
{
Console.WriteLine(deChild.Name);
}

(b) Get all members of a group:

DirectoryEntry deGroup = new
DirectoryEntry("LDAP://cn=MyGroup,dc=fabrikam,dc=com");

foreach(string strMember in deGroup.Properties["member"])
{
Console.WriteLine(strMember);
}

Sure they're diferent - but as I tried to point out, that's because
they represent fundamentally different things. But really, this code
is not in any way hard, or tricky, or difficult or anything, right?

HTH
Marc
================================================================
Marc Scheuner May The Source Be With You!
Berne, Switzerland m.scheuner -at- inova.ch
 
J

Joe User

1st - great stuff - thanks for the follow up -

2nd - to answer the last question first, no what you wrote was not
complicated, and yes it was exactly as I would have envisioned doing it when
I first started. What I ended up with was the following (with minor edits):
Private Sub Update_Users_in_Group()
Dim objGroup As New System.DirectoryServices.DirectoryEntry( _

mainDirectoryEntry.Children.Find(cbGroups.Items(cbGroups.SelectedIndex)).Pat
h & ",Group")
Dim objMemberuser As System.DirectoryServices.DirectoryEntry
Dim objMembers As Object
Dim objMember As Object

lbGrpUsers.Items.Clear()

'working method using native methods
objMembers = objGroup.Invoke("Members", Nothing) 'returns COM
object...
For Each objMember In objMembers
'Next line brings COM object member into .Net world
objMemberuser = New
System.DirectoryServices.DirectoryEntry(objMember)
lbGrpUsers.Items.Add(objMemberuser.Name)
Next

End Sub

I cut out most of my work-in-progress type comments and hopefully didn't
over-do it... also - 'lbGrpUsers' is a list box, and 'cbGroups' is a
comboBox, both on the main panel. I had experimented with the invocation
(as shown) attempting to shorten the whole process of getting to the member
names, but didn't succeed. As you may guess, with this approach - at least
to me - the process to take this one step further and manipulate the objects
was far less clear with my code than it would appear to be by your code.
Prior to this I did experiment with the DirectoryEntry's 'Properties' with
no luck - hence this approach - but this I will have to re-visit now.

3rd - WinNT obsolete ? - somehow I missed that or disregarded it in the
past. Looks like another change of approach coming... at least some more
reading.

Thanks
- J

Marc Scheuner said:
Well - that explains why it hasn't worked! Is there somewhere that this is
documented ? To be more specific - it would appear from the intent of the
class that this is exactly what the .children property was intended to
support.

No, that assumption would be wrong. Being part of an OU, and member of
a group, are two fundamentally different things - hence the different
ways of modelling them.

Any user can be inside only one given OU at any time - he has to be in
a container of sorts (OU, or generic container) at all times. But as I
said - you can never be inside more than a single container.

Group membership is very different - you can be associated with any
number of groups - you're not physically *IN* that group - you just
belong to it.

It's like in the real world - you can physically only be in one given
room or building at any given point in time, but you can be member of
many groups (professional organisation, sports club, what have you)
simultaneously.
WRT .Members, I've got
working code to invoke the call to .Members - but this approach just
complicates anything else I would want to do with the objects in the
directory - and kind of defeats the purpose of this class - making .Net less
attractive than other options.

Too bad - but that's the way it is. If you use the LDAP provider
(rather than the OBSOLETE, supported-only-for-backwards-compatibility
WinNT provider); using .NET (C#, VB.NET) is in fact a LOT easier than
going by the straight old-style ADSI interfaces.....

(a) Get all objects inside an OU:

DirectoryEntry deOU = new
DirectoryEntry("LDAP://ou=MyOU,dc=fabrikam,dc=com");

foreach(DirectoryEntry deChild in deOU.Children)
{
Console.WriteLine(deChild.Name);
}

(b) Get all members of a group:

DirectoryEntry deGroup = new
DirectoryEntry("LDAP://cn=MyGroup,dc=fabrikam,dc=com");

foreach(string strMember in deGroup.Properties["member"])
{
Console.WriteLine(strMember);
}

Sure they're diferent - but as I tried to point out, that's because
they represent fundamentally different things. But really, this code
is not in any way hard, or tricky, or difficult or anything, right?

HTH
Marc
================================================================
Marc Scheuner May The Source Be With You!
Berne, Switzerland m.scheuner -at- inova.ch
 
M

Marc Scheuner [MVP ADSI]

3rd - WinNT obsolete ? - somehow I missed that or disregarded it in the
past. Looks like another change of approach coming... at least some more
reading.


Well, the whole WinNT provider model is simply in AD because of the
"old" NT4 domain model - flat domains, no hierarchy etc.

Thus, with WinNT, you'll only ever get a very limited set of
properties (those that existed in the NT4 SAM), you'll only get a flat
list of users and groups (WinNT doesn't know nothing about OU's and
hierarchy and so on), and the WinNT code base is not being developed
any further.

If you're doing any serious Active Directory stuff, you GOTTA get used
to using LDAP ! :)

Marc
================================================================
Marc Scheuner May The Source Be With You!
Berne, Switzerland m.scheuner -at- inova.ch
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top