Adding and removing users from Active Directory groups in .NET
Asked Answered
H

4

55

I am writing the following methods to add and remove users from active directory in C#.

void AddUserToGroup(string userId, string groupName);
void RemoveUserFromGroup(string userId, string groupName);

How best to implement these methods?

Here is some code from CodeProject. I can't see where the AD server is specified in these examples though? (is it implicitly supplied by the .NET framework when using the LDAP protocol?). Are these examples worth following?

public void AddToGroup(string userDn, string groupDn)
{
    try
    {
        DirectoryEntry dirEntry = new DirectoryEntry("LDAP://" + groupDn);
        dirEntry.Properties["member"].Add(userDn);
        dirEntry.CommitChanges();
        dirEntry.Close();
    }
    catch (System.DirectoryServices.DirectoryServicesCOMException E)
    {
        //doSomething with E.Message.ToString();

    }
}


public void RemoveUserFromGroup(string userDn, string groupDn)
{
    try
    {
        DirectoryEntry dirEntry = new DirectoryEntry("LDAP://" + groupDn);
        dirEntry.Properties["member"].Remove(userDn);
        dirEntry.CommitChanges();
        dirEntry.Close();
    }
    catch (System.DirectoryServices.DirectoryServicesCOMException E)
    {
        //doSomething with E.Message.ToString();

    }
}
Hokkaido answered 26/1, 2010 at 22:12 Comment(0)
M
102

Ugh. LDAP. If you're using the .Net Framework 3.5 or above, I highly recommend using the System.DirectoryServices.AccountManagement namespace. That makes things so much easier.

public void AddUserToGroup(string userId, string groupName) 
{ 
    try 
    { 
        using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, "COMPANY"))
        {
            GroupPrincipal group = GroupPrincipal.FindByIdentity(pc, groupName);
            group.Members.Add(pc, IdentityType.UserPrincipalName, userId);
            group.Save();
        }
    } 
    catch (System.DirectoryServices.DirectoryServicesCOMException E) 
    { 
        //doSomething with E.Message.ToString(); 

    } 
} 

public void RemoveUserFromGroup(string userId, string groupName)
{   
    try 
    { 
        using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, "COMPANY"))
        {
            GroupPrincipal group = GroupPrincipal.FindByIdentity(pc, groupName);
            group.Members.Remove(pc, IdentityType.UserPrincipalName, userId);
            group.Save();
        }
    } 
    catch (System.DirectoryServices.DirectoryServicesCOMException E) 
    { 
        //doSomething with E.Message.ToString(); 

    }
}
Marsala answered 27/1, 2010 at 0:26 Comment(16)
System.DirectorServices.AccountManagement is only available in >= 3.5, rather than 3.0Sverige
Below code worked for me group.Members.Remove(UserPrincipal.FindByIdentity(pc, userId)); instead of "group.Members.Remove(pc, IdentityType.UserPrincipalName, userId);" . Note: my user id is just "USERNAME" without appending with domain nameHypersensitive
Yeah, that overload works, too, it's just an extra call into the LDAP service to get the user identity before sending the remove call. Frankly, it's possible that they're equivalent in function as the API probably calls into the LDAP for the identity based on user name before doing the remove, too.Marsala
Had a similar issue to the described above. I had to change the line that removes the user from the group from IdentityType.UserPrincipalName to IdentityType.SAMAccountNameUmbilicate
What is userId ?Barbarossa
The only issue with the System.DirectorServices.AccountManagement is that if the machine is not in the domain it gets me an error >.<Strauss
I know it was said in the above comments, but it wasn't clarified. If you send in DOMAIN\someUserId as your user, that's when you have to change it to IdentityType.SamAccountName, instead of UserPrincipalName. The latter will give you an exception: No principal matching the specified parameters was found. But note, too, it will also give you an exception with SamAccountName, if the user is already in the group.Gastelum
On the removal from the group - if the user was never in the group to begin with, it doesn't provide an exception - it will just go through the .Save() operation, regardless. You have to check if the UserPrincipal object for the user .IsMemberOf(group), to discover this. Submitted an edit. userId should be in DOMAIN\username form to send to UserPrincipal.FindByIdentity(pc, userId);, however, which would require SamAccountName in the IdentityType.Gastelum
@Rama I would post that as a separate answer--that helped me a ton!Ricercare
What does company means in that both method?Segarra
@Gastelum Getting this error- No principal matching the specified parameters was found.'Nitrogenous
@Nitrogenous Read my comments above. I specified why that happens. Use IdentityType.SamAccountName, instead, but then you have to make sure they are not in the group, to begin with, too. Do you know they are in the group, but are not getting found? Then you can look for them by their SSID.Gastelum
I kept getting System.DirectoryServices.DirectoryServicesCOMException (0x8007052E): The user name or password is incorrect. To fix it, I had to provide a user and password in the new PrincipalContext(ContextType.Domain ....) constructor. I think this is because I am running as a local account, trying to add a domain user to a local group. It works now, thanks!Sanbo
This solution is not working if login user is non owner of AD group do we have any solution that non owner can add user in AD Group?Mitten
@JasminSolanki That seems contrary to the point of AD. You have to have permission to add/remove from an AD group to add or remove people from an AD group...Marsala
In these examples remember that UserPrincipal and GroupPrincipal are disposable and should be prefixed with using when declaring the variables. The sample code in the answer is not disposing GroupPrincipal.Meperidine
C
5

The server is part of the groupDn variable value. For example:

LDAP://myServer/CN=MyGroup,CN=Groups,CN=MyContainer,DN=mydomain.com

The whole thing is the LDAP path for the group. The first part (myServer) is the server name.

The part after the server name (e.g. CN=...) is the DN (distinguished name) of the group.

Colorful answered 26/1, 2010 at 22:15 Comment(2)
The only thing I would say is that in a good AD setup, you should not have to specify the server. The .NET AD/low level AD calls should resolve the nearest available server for you. But this is more AD/domain setup and not so much code. If your AD setup is solid, you should be able to exclude the server (e.g. LDAP://CN=MyGroup,CN=Groups,CN=MyContainer,DN=mydomain.com)Colorful
Sorry didn't really answer your questions. yes, the examples do seem clean. If you are still unsure, I highly recommend the .NET Developer's Guide to Directory Services Programming (amazon.com/gp/product/0321350170)Colorful
D
2

When deleting a member in public void RemoveUserFromGroup(string userDn, string groupDn)

dirEntry.Properties["member"].Remove(userDn) does not work for me.

dirEntry.Properties["member"].RemoveAt(dn.IndexOf(dn)) works.

Diachronic answered 26/1, 2012 at 9:36 Comment(3)
What is the dn variable?Aesculapius
@fripp13, in the context of an Active Directory, dn almost always means DistinguishedName.Lengthen
@Diachronic The RemoveAt(int) method requires an index. If you call userDn.IndexOf(userDn), the method will always return 0 (Example: "TEST".IndexOf("TEST") will return 0). The 2nd proposal will always remove the first entry in the list.Techy
R
1

You can put the LDAP server in the path argument to DirectoryEntry, so "LDAP://" + ldapServer + ldapQuery.

Use the DirectoryEntry(String path, String userId, String password) if you need to authenticate

Revisionism answered 26/1, 2010 at 22:16 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.