Just saw this being discussed internally and thought that it was quite useful to a lot of you out there so I thought I'd share. The true boolean to grp.GetMembers tells it to recursively get the nested group members too. I tested this out on discussion groups, security groups, with users and computers and works as expected.
public static string groupName = string.Empty;
public static string domainName = string.Empty;
static void Main(string args)
groupName = args;
domainName = args;
PrincipalContext ctx = new PrincipalContext(ContextType.Domain, domainName);
GroupPrincipal grp = GroupPrincipal.FindByIdentity(ctx, IdentityType.Name, groupName);
if (grp != null)
foreach (Principal p in grp.GetMembers(true))
Console.WriteLine(p.Name); //You can add more attributes, samaccountname, UPN, DN, object type, etc...
Console.WriteLine("\nWe did not find that group in that domain, perhaps the group resides in a different domain?");
Update: If you use this code and it blows up with a certain group with the exception: There is no such object on the server.
In my case the user it kept blowing up on was a deleted account which still was persistent in the directory because it had not been garbage collected yet. When I ran the exe with elevated permission it completed as expected, but as a regular account you cannot see the object and therefore the framework doesn’t handle this.
This is most valuable, thanks!
PrincipalContext should be disposed.
using (PrincipalContext ctx = new PrincipalContext(ContextType.Domain, domainName))