By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,142 Members | 1,900 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,142 IT Pros & Developers. It's quick & easy.

Using Generics with System.DirectoryServices

P: n/a
Hi,

I'm in the process of updating an ASP.NET v1.1 web app to v2. The app uses
ActiveDirectory a great deal, and I'm trying to use the new
System.Collections.Generic namespace where possible, having been advised by
several luminaries that that is a "good thing to do"... :-)

However, I'm experiencing a problem with the IEnumerable interface. (N.B. I
understand fully that I should be using the LDAP provider instead of the
WinNT provider - I'm in the process of fixing that too, but that's not my
most pressing problem.)

I use the following function to return a list of all users in a group:

using System;
using System.Collections;
using System.Collections.Generic;
using System.DirectoryServices;

public static List<stringGetGroupsForUser(string pstrUser)
{
DirectoryEntry objADEntry = null;
DirectoryEntry objUser = null;
object objChildren = null;
List<stringlstGroups = new List<string>();

try
{
objADEntry = new DirectoryEntry("WinNT://" + mstrDomain + ",
domain");
objUser = objADEntry.Children.Find(pstrUser, "user");
objChildren = objUser.Invoke("Groups");
foreach (object objChild in (IEnumerable)objChildren)
{
DirectoryEntry objGroup = new DirectoryEntry(objChild);
lstGroups.Add(objGroup.Name.ToLower());
}
return lstGroups;
}
catch (Exception)
{
throw;
}
}
It works well enough. However, when I rem out the using System.Collections;
namespace reference, the code fails and tells me that there is no support
for IEnumerable taking no arguments. Fair enough.

If I amend the line in question to:

foreach (object objChild in (IEnumerable<DirectoryEntries>)objChildren)

That returns the following error:

Unable to cast COM object of type 'System.__ComObject' to interface type
'System.Collections.Generic.IEnumerable`1[System.DirectoryServices.DirectoryEntries]'.
This operation failed because the QueryInterface call on the COM component
for the interface with IID '{AEF9EC8A-1E73-365B-8DA2-800A3A6166E6}' failed
due to the following
error: No such interface supported (Exception from HRESULT: 0x80004002
(E_NOINTERFACE)).
At this point, I'm pretty much out of my depth. Therefore, I'd be grateful
to know:

1) if what I'm doing is a worthwhile exercise, or whether I should just
continue with the old IEnumerable object in the old System.Collections
namespace

2) apart from replacing WinNT with LDAP, which I'm in the process of doing,
is there a more efficient method for returning a list of groups to which a
user belongs?
Any assistance gratefully received.

Mark
Oct 10 '06 #1
Share this Question
Share on Google+
6 Replies


P: n/a
All of my apps that use AD are still on .NET 1.1, but to the best of my
knowledge there have been a number of changes to DirectoryServices in
..net 2.0

First, I never used the WinNT objects, I always used LDAP. I didn't
need backwards compatibility and it just worked the first time I tried
it, so in that sense I'm not sure how the WinNT query prefix works

For more information on DirectoryServices take a look here:

http://msdn.microsoft.com/library/de..._providers.asp

that link talks about the ADSI providers which probably supports
generics. The method your trying doesn't seem to support generics,
especially since it seems to be returning a COM object.

hope that helps!

sean

Mark Rae wrote:
Hi,

I'm in the process of updating an ASP.NET v1.1 web app to v2. The app uses
ActiveDirectory a great deal, and I'm trying to use the new
System.Collections.Generic namespace where possible, having been advised by
several luminaries that that is a "good thing to do"... :-)

However, I'm experiencing a problem with the IEnumerable interface. (N.B. I
understand fully that I should be using the LDAP provider instead of the
WinNT provider - I'm in the process of fixing that too, but that's not my
most pressing problem.)

I use the following function to return a list of all users in a group:

using System;
using System.Collections;
using System.Collections.Generic;
using System.DirectoryServices;

public static List<stringGetGroupsForUser(string pstrUser)
{
DirectoryEntry objADEntry = null;
DirectoryEntry objUser = null;
object objChildren = null;
List<stringlstGroups = new List<string>();

try
{
objADEntry = new DirectoryEntry("WinNT://" + mstrDomain + ",
domain");
objUser = objADEntry.Children.Find(pstrUser, "user");
objChildren = objUser.Invoke("Groups");
foreach (object objChild in (IEnumerable)objChildren)
{
DirectoryEntry objGroup = new DirectoryEntry(objChild);
lstGroups.Add(objGroup.Name.ToLower());
}
return lstGroups;
}
catch (Exception)
{
throw;
}
}
It works well enough. However, when I rem out the using System.Collections;
namespace reference, the code fails and tells me that there is no support
for IEnumerable taking no arguments. Fair enough.

If I amend the line in question to:

foreach (object objChild in (IEnumerable<DirectoryEntries>)objChildren)

That returns the following error:

Unable to cast COM object of type 'System.__ComObject' to interface type
'System.Collections.Generic.IEnumerable`1[System.DirectoryServices.DirectoryEntries]'.
This operation failed because the QueryInterface call on the COM component
for the interface with IID '{AEF9EC8A-1E73-365B-8DA2-800A3A6166E6}' failed
due to the following
error: No such interface supported (Exception from HRESULT: 0x80004002
(E_NOINTERFACE)).
At this point, I'm pretty much out of my depth. Therefore, I'd be grateful
to know:

1) if what I'm doing is a worthwhile exercise, or whether I should just
continue with the old IEnumerable object in the old System.Collections
namespace

2) apart from replacing WinNT with LDAP, which I'm in the process of doing,
is there a more efficient method for returning a list of groups to which a
user belongs?
Any assistance gratefully received.

Mark
Oct 10 '06 #2

P: n/a
"Sean Chambers" <dk****@gmail.comwrote in message
news:11**********************@m7g2000cwm.googlegro ups.com...
The method your trying doesn't seem to support generics,
especially since it seems to be returning a COM object.
Er, my method is returning a List<stringobject...
hope that helps!
I'm afraid it doesn't really... But it's the only reply I've had, so thanks
for that... :-)
Oct 10 '06 #3

P: n/a
The method your trying doesn't seem to support generics,
especially since it seems to be returning a COM object.

Er, my method is returning a List<stringobject...
I was referring to the foreach where you are trying to cast a COM
object to a string.

I don't have any experience with com, perhaps I am confused?

Oct 10 '06 #4

P: n/a

"Mark Rae" <ma**@markNOSPAMrae.comwrote in message
news:%2******************@TK2MSFTNGP02.phx.gbl...
| Hi,
|
| I'm in the process of updating an ASP.NET v1.1 web app to v2. The app uses
| ActiveDirectory a great deal, and I'm trying to use the new
| System.Collections.Generic namespace where possible, having been advised
by
| several luminaries that that is a "good thing to do"... :-)
|
| However, I'm experiencing a problem with the IEnumerable interface. (N.B.
I
| understand fully that I should be using the LDAP provider instead of the
| WinNT provider - I'm in the process of fixing that too, but that's not my
| most pressing problem.)
|
| I use the following function to return a list of all users in a group:
|
| using System;
| using System.Collections;
| using System.Collections.Generic;
| using System.DirectoryServices;
|
| public static List<stringGetGroupsForUser(string pstrUser)
| {
| DirectoryEntry objADEntry = null;
| DirectoryEntry objUser = null;
| object objChildren = null;
| List<stringlstGroups = new List<string>();
|
| try
| {
| objADEntry = new DirectoryEntry("WinNT://" + mstrDomain + ",
| domain");
| objUser = objADEntry.Children.Find(pstrUser, "user");
| objChildren = objUser.Invoke("Groups");
| foreach (object objChild in (IEnumerable)objChildren)
| {
| DirectoryEntry objGroup = new DirectoryEntry(objChild);
| lstGroups.Add(objGroup.Name.ToLower());
| }
| return lstGroups;
| }
| catch (Exception)
| {
| throw;
| }
| }
|
|
| It works well enough. However, when I rem out the using
System.Collections;
| namespace reference, the code fails and tells me that there is no support
| for IEnumerable taking no arguments. Fair enough.
|
| If I amend the line in question to:
|
| foreach (object objChild in (IEnumerable<DirectoryEntries>)objChildren)
|
| That returns the following error:
|
| Unable to cast COM object of type 'System.__ComObject' to interface type
|
'System.Collections.Generic.IEnumerable`1[System.DirectoryServices.DirectoryEntries]'.
| This operation failed because the QueryInterface call on the COM component
| for the interface with IID '{AEF9EC8A-1E73-365B-8DA2-800A3A6166E6}' failed
| due to the following
| error: No such interface supported (Exception from HRESULT: 0x80004002
| (E_NOINTERFACE)).
|
|
| At this point, I'm pretty much out of my depth. Therefore, I'd be grateful
| to know:
|
| 1) if what I'm doing is a worthwhile exercise, or whether I should just
| continue with the old IEnumerable object in the old System.Collections
| namespace
|
| 2) apart from replacing WinNT with LDAP, which I'm in the process of
doing,
| is there a more efficient method for returning a list of groups to which a
| user belongs?
|
|
| Any assistance gratefully received.
|
| Mark
|
|

WinNT and LDAP (the providers) implement a diferent object model, so you
can't use the following sample to query group membership in a NT4 domain.

// search all groups myUser is member a of.
// use server or FastBind binding for the fastest way to query the AD.
using(DirectoryEntry user = new DirectoryEntry("LDAP://..., cn=myUser,
cn=.., dn=..", AuthenticationTypes.FastBind))
{
PropertyCollection pcoll = user.Properties;
PropertyValueCollection memberOf = pcoll["memberOf"];
foreach(string group in memberOf)
lstGroups.Add(group);
}

note also that the AD hierarchy differs considerable from NT4's SAM object
model, so the data returned is in the "common name "format (that is :
CN=...) instead of a simple SAM account name.

Willy.
Oct 10 '06 #5

P: n/a
"Willy Denoyette [MVP]" <wi*************@telenet.bewrote in message
news:eU**************@TK2MSFTNGP05.phx.gbl...
WinNT and LDAP (the providers) implement a diferent object model, so you
can't use the following sample to query group membership in a NT4 domain.
That's fine - it's a Win2k3 domain.
using(DirectoryEntry user = new DirectoryEntry("LDAP://..., cn=myUser,
cn=.., dn=..", AuthenticationTypes.FastBind))
That generates an error saying that there's no overload for DirectoryEntry
taking 2 arguments...

However, I'll perservere... :-)
Oct 10 '06 #6

P: n/a
"Mark Rae" <ma**@markNOSPAMrae.comwrote in message
news:%2****************@TK2MSFTNGP03.phx.gbl...
However, I'll perservere... :-)
Persevered and succeeded :-) New code, with the added advantage of having
removed the reliance on the WinNT provider, follows:

public static List<stringGetGroupsForUser(string pstrUser)
{
DirectorySearcher objDS = null;
SearchResult objSR = null;
DirectoryEntry objUser = null;
List<stringlstGroups = new List<string>();

try
{
objDS = new DirectorySearcher("objectCategory=User");
objDS.Filter = "(SAMAccountName=" + pstrUser + ")";
objSR = objDS.FindOne();
objUser = new DirectoryEntry(objSR.Path);

PropertyCollection colProperties = objUser.Properties;
PropertyValueCollection colPropertyValues =
colProperties["memberOf"];
foreach (string strGroup in colPropertyValues)
{
lstGroups.Add(GetSAMAccountName(strGroup).ToLower( ));
}
return lstGroups;
}
catch (Exception)
{
throw;
}
}

GetSAMAccountName is, as its name suggests, another method in my ADSI
wrapper class which takes an LDAP path and returns the SAMAccountName -
thanks again for your help.
Oct 10 '06 #7

This discussion thread is closed

Replies have been disabled for this discussion.