473,324 Members | 2,268 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,324 software developers and data experts.

Get list of the Groups a User belongs to

How can I get a list of the Groups both Local and Domain groups a User
belongs to.
Dec 9 '06 #1
10 26759
Hi,

On a Windows Server 2003 domain you can construct a WindowsIdentity by
passing in the user's name in the form, name@domain:

"WindowsIdentity(String) Constructor"
http://msdn2.microsoft.com/en-us/library/td3046fc.aspx

Then you can access the Groups property (2.0 framework only):

"WindowsIdentity.Groups Property"
http://msdn2.microsoft.com/en-us/lib...ty.groups.aspx

If you can't use the above solution since you are using a different version
of the framework or a different domain then I think you'll have to resort to
the unmanaged APIs such as LogonUser:

"LogonUser"
http://msdn2.microsoft.com/en-us/library/aa378184.aspx

The above will get you the User's token, which you can pass to the following
function:

"GetTokenInformation"
http://msdn2.microsoft.com/en-us/library/aa446671.aspx

Specify the value of TOKEN_GROUPS for the TokenInformationClass argument.

(Note that I haven't used these APIs myself)

You'll have to use P/Invoke for this, of course :)

--
Dave Sexton

"Jeff Williams" <je***********@hardsoft.com.auwrote in message
news:12*************@corp.supernews.com...
How can I get a list of the Groups both Local and Domain groups a User
belongs to.

Dec 9 '06 #2
"Dave Sexton" <dave@jwa[remove.this]online.comwrote in message
news:uT*************@TK2MSFTNGP02.phx.gbl...
You'll have to use P/Invoke for this, of course :)
System.DirectoryServices will do all of this, and much more, for you without
recourse to p/invoke...

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

public static List<stringGetGroupsForUser(string pstrUser)
{
/// <summary>
/// Gets the groups a user is a member of
/// </summary>
/// <param name="pstrGroup">ActiveDirectory group to evaluate</param>
/// <returns>List<stringof groups for pstrUser</returns>

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;
}
finally
{
if (objUser != null)
{
objUser.Close();
objUser.Dispose();
objUser = null;
}
if (objSR != null)
{
objSR = null;
}
if (objDS != null)
{
objDS.Dispose();
objDS = null;
}
}
}

public static string GetSAMAccountName(string pstrPath)
{
/// <summary>
/// Gets a SAM Account Name from a given LDAP path
/// </summary>
/// <param name="pstrPath">LDAP path to bind to</param>

DirectoryEntry objADEntry = null;

try
{
objADEntry = new DirectoryEntry("LDAP://" + pstrPath);
return objADEntry.Properties["SAMAccountName"].Value.ToString();
}
catch (System.Runtime.InteropServices.COMException)
{
return String.Empty;
}
catch (System.NullReferenceException)
{
return String.Empty;
}
catch (Exception)
{
throw;
}
finally
{
if (objADEntry != null)
{
objADEntry.Close();
objADEntry.Dispose();
objADEntry = null;
}
}
}
Dec 9 '06 #3
"Mark Rae" <ma**@markNOSPAMrae.comwrote in message
news:OH**************@TK2MSFTNGP04.phx.gbl...
"Dave Sexton" <dave@jwa[remove.this]online.comwrote in message
news:uT*************@TK2MSFTNGP02.phx.gbl...
>You'll have to use P/Invoke for this, of course :)

System.DirectoryServices will do all of this, and much more, for you without recourse to
p/invoke...

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

public static List<stringGetGroupsForUser(string pstrUser)
{
/// <summary>
/// Gets the groups a user is a member of
/// </summary>
/// <param name="pstrGroup">ActiveDirectory group to evaluate</param>
/// <returns>List<stringof groups for pstrUser</returns>

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;
}
finally
{
if (objUser != null)
{
objUser.Close();
objUser.Dispose();
objUser = null;
}
if (objSR != null)
{
objSR = null;
}
if (objDS != null)
{
objDS.Dispose();
objDS = null;
}
}
}

public static string GetSAMAccountName(string pstrPath)
{
/// <summary>
/// Gets a SAM Account Name from a given LDAP path
/// </summary>
/// <param name="pstrPath">LDAP path to bind to</param>

DirectoryEntry objADEntry = null;

try
{
objADEntry = new DirectoryEntry("LDAP://" + pstrPath);
return objADEntry.Properties["SAMAccountName"].Value.ToString();
}
catch (System.Runtime.InteropServices.COMException)
{
return String.Empty;
}
catch (System.NullReferenceException)
{
return String.Empty;
}
catch (Exception)
{
throw;
}
finally
{
if (objADEntry != null)
{
objADEntry.Close();
objADEntry.Dispose();
objADEntry = null;
}
}
}
Just a few remarks:
You may simplify your code and make it easier to read and maintain by applying the *using*
idiom, this way, you get rid of the Dispose, Close and completely redundant "obj = null"
calls.
Your code will only work when the caller is running in his domain account, when this is not
the case, you need to bind explicitly against the Domain or the DC, and preferably using
FastBind for performance reasons. You may also bind to the GC (the Global Catalog) using
GC://... in order to speed-up the queries.
Another point to consider is that the binding user must have "query" privileges to all of
the objects you query, normally all domain member do have this privilege, but highly secured
AD's may restrict access to some objects to special accounts only. So it's possible that a
user can bind to his user object, but not to (some) of the related objects.
You should also try to reuse the already established DirectoryEntry object for further
operations against the AD, the way you do forces adsi to rebind and this can be a costly
operation especially on slow connections and uses a lot more resources at the LDAP server.
The following code snip shows how to take advantage of a single bind by using the
GetDirectorEntry() for each successive object retrieval.

public static List<stringGetGroupsForUser(string userAccount)
{
string rootPath = "LDAP://{0}/DC=xxx,DC=yyy,DC=zzz";
string accountDomain = "domain"; // domain name or dc name or empty when binding to
logon domain
string userAccount = userAccount
rootPath = String.Format(
rootPath

, accountDomain);
string authUser = "xxx\yyyyy"; // account used to bind, here hardcoded, not
production safe!
string authPassword = "PASSWORD"; // his password, here hardcoded, not production
safe!

List<stringlstGroups = new List<string>();
using (DirectoryEntry root = new DirectoryEntry(rootPath, authUser, authPassword,
AuthenticationTypes.FastBind))
{
using (DirectorySearcher ds = new DirectorySearcher(root))
{
SearchResult sr = null;
ds.Filter = "(SAMAccountName=" + userAccount + ")";
sr = ds.FindOne();
using (DirectoryEntry user = sr.GetDirectoryEntry())
{
PropertyCollection pcoll = user.Properties;
PropertyValueCollection memberOf = pcoll["memberOf"];
foreach (string cnGroup in memberOf)
{
ds.Filter = cnGroup.Substring(0, cnGroup.IndexOf(','));
sr = ds.FindOne();
using (DirectoryEntry group = sr.GetDirectoryEntry())
{
lstGroups.Add(group.Properties["SAMAccountName"].Value.ToString());
}
}
}
}
}
return lstGroups;
}
....

Willy.

Dec 9 '06 #4
"Willy Denoyette [MVP]" <wi*************@telenet.bewrote in message
news:ui**************@TK2MSFTNGP04.phx.gbl...
You may simplify your code... <snip>
It's not actually my code - I just found it on the web with a simple Google
search...
Dec 9 '06 #5
Hi Mark,

Good stuff, but correct me if I'm wrong here. That won't get the local
groups so the user will still have to use my method anyway.

--
Dave Sexton

"Mark Rae" <ma**@markNOSPAMrae.comwrote in message
news:OH**************@TK2MSFTNGP04.phx.gbl...
"Dave Sexton" <dave@jwa[remove.this]online.comwrote in message
news:uT*************@TK2MSFTNGP02.phx.gbl...
>You'll have to use P/Invoke for this, of course :)

System.DirectoryServices will do all of this, and much more, for you
without recourse to p/invoke...

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

public static List<stringGetGroupsForUser(string pstrUser)
{
/// <summary>
/// Gets the groups a user is a member of
/// </summary>
/// <param name="pstrGroup">ActiveDirectory group to evaluate</param>
/// <returns>List<stringof groups for pstrUser</returns>

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;
}
finally
{
if (objUser != null)
{
objUser.Close();
objUser.Dispose();
objUser = null;
}
if (objSR != null)
{
objSR = null;
}
if (objDS != null)
{
objDS.Dispose();
objDS = null;
}
}
}

public static string GetSAMAccountName(string pstrPath)
{
/// <summary>
/// Gets a SAM Account Name from a given LDAP path
/// </summary>
/// <param name="pstrPath">LDAP path to bind to</param>

DirectoryEntry objADEntry = null;

try
{
objADEntry = new DirectoryEntry("LDAP://" + pstrPath);
return objADEntry.Properties["SAMAccountName"].Value.ToString();
}
catch (System.Runtime.InteropServices.COMException)
{
return String.Empty;
}
catch (System.NullReferenceException)
{
return String.Empty;
}
catch (Exception)
{
throw;
}
finally
{
if (objADEntry != null)
{
objADEntry.Close();
objADEntry.Dispose();
objADEntry = null;
}
}
}

Dec 9 '06 #6
"Dave Sexton" <dave@jwa[remove.this]online.comwrote in message
news:ui**************@TK2MSFTNGP04.phx.gbl...
Good stuff, but correct me if I'm wrong here. That won't get the local
groups so the user will still have to use my method anyway.
No it won't, but it can with a fairly trivial modification:
http://www.experts-exchange.com/Prog..._20658471.html
Dec 9 '06 #7
Hi Mark,

That's great :)

--
Dave Sexton

"Mark Rae" <ma**@markNOSPAMrae.comwrote in message
news:uG**************@TK2MSFTNGP06.phx.gbl...
"Dave Sexton" <dave@jwa[remove.this]online.comwrote in message
news:ui**************@TK2MSFTNGP04.phx.gbl...
>Good stuff, but correct me if I'm wrong here. That won't get the local
groups so the user will still have to use my method anyway.

No it won't, but it can with a fairly trivial modification:
http://www.experts-exchange.com/Prog..._20658471.html

Dec 9 '06 #8
"Dave Sexton" <dave@jwa[remove.this]online.comwrote in message
news:eR**************@TK2MSFTNGP02.phx.gbl...
That's great :)
By the way, if you do intend to use the code I found, be sure to follow
Willy's recommended modifications...
Dec 9 '06 #9
"Dave Sexton" <dave@jwa[remove.this]online.comwrote in message
news:ui**************@TK2MSFTNGP04.phx.gbl...
Hi Mark,

Good stuff, but correct me if I'm wrong here. That won't get the local groups so the user
will still have to use my method anyway.

--

No, you can use the WinNT provider to connect to the local SAM, like this:

private static List<stringAccountGroups(string userAccount)
{
List<stringlstGroups = new List<string>(10);
string adsPath = "WinNT://<domain>/<machine>"; // or WinNT://<machine if not a
domain member.
using (DirectoryEntry groupEntry = new DirectoryEntry(adsPath +",computer"))
{
IADsContainer cont = groupEntry.NativeObject as IADsContainer;
object[] filter = {"Group"};
cont.Filter = filter;
foreach (IADsGroup group in cont) {
if(group.IsMember(adsPath + "/" + userAccount))
lstGroups.Add(group.Name);
}
}
return lstGroups;
}

the problem here is that you need to set a reference to activeds.tlb. Also note that the
above sample does not account for nested groups!!
Note that you can also use WindowsIdentity.Groups, the problem here is that you also get the
pseudo accounts returned.

A better solution is to use System.Management (and WMI classes "Win32_UserAccount" and
"Win32_Group") to check local account and group membership.
Willy.

Dec 9 '06 #10
Hi Willy,

Thanks for the info.

--
Dave Sexton

"Willy Denoyette [MVP]" <wi*************@telenet.bewrote in message
news:uk**************@TK2MSFTNGP05.phx.gbl...
"Dave Sexton" <dave@jwa[remove.this]online.comwrote in message
news:ui**************@TK2MSFTNGP04.phx.gbl...
>Hi Mark,

Good stuff, but correct me if I'm wrong here. That won't get the local
groups so the user will still have to use my method anyway.

--


No, you can use the WinNT provider to connect to the local SAM, like this:

private static List<stringAccountGroups(string userAccount)
{
List<stringlstGroups = new List<string>(10);
string adsPath = "WinNT://<domain>/<machine>"; // or
WinNT://<machine if not a domain member.
using (DirectoryEntry groupEntry = new DirectoryEntry(adsPath
+",computer"))
{
IADsContainer cont = groupEntry.NativeObject as IADsContainer;
object[] filter = {"Group"};
cont.Filter = filter;
foreach (IADsGroup group in cont) {
if(group.IsMember(adsPath + "/" + userAccount))
lstGroups.Add(group.Name);
}
}
return lstGroups;
}

the problem here is that you need to set a reference to activeds.tlb. Also
note that the above sample does not account for nested groups!!
Note that you can also use WindowsIdentity.Groups, the problem here is
that you also get the pseudo accounts returned.

A better solution is to use System.Management (and WMI classes
"Win32_UserAccount" and "Win32_Group") to check local account and group
membership.
Willy.

Dec 9 '06 #11

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
by: Bas | last post by:
I need to know if there is a way in Microsoft SQL Server 2000 to determine which Windows groups a user belongs to if logging into the database under Windows Authentication. I am making a tool to...
3
by: RCCNH | last post by:
I am creating a Windows application using C# in .NET. In one of the windows, I have to show a scrollable list of user objects. Those user objects contain various controls themselves (textbox,...
3
by: Gonçalo Boléo | last post by:
How do i list the groups a user belong using AD? thanks, Gonçalo Boléo
1
by: Mad Scientist Jr | last post by:
I would like to write a vb.asp.net function Private Function fn_sGetRoles(byval sDelimiter as string) As String that simply returns a delimited list of all the roles a user belongs to. I...
2
by: Kevin Wen | last post by:
Hi Sirs, How could i determine if an user belongs to a specific group, especially nested group. thanks, -Kevin
3
by: Matt | last post by:
I am trying to write some code that will find all the groups that a user is a member of Does anyone know how to do this in VB.NET Thanks in advanc Matt
8
by: tlyczko | last post by:
I am developing an Access database that will be used by some users logging into Citrix servers. Using the "Code 1" listing, 'fGetFullNameOfLoggedUser' from Dev Ashish's site, which I found in...
4
by: Cleyton | last post by:
Hello! I need to get the user groups in a machine, because i need to verify dynamically what's the name of the group "Everyone" in different windows. For example, in windows in portuguese the...
4
by: Dan | last post by:
Hi Group Memebers: I am pretty new to asp.net.vb. Please dont mistake me if my Q is silly... I want to list the user names online in home page.... I am adopting this metod: Get the user...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.