Principal Error in AD when user is in group?

0

I have the following code, which works fine, as long as the user isn't in defined group (groupName)

all values are defined in this function or somewhere else and are implemented correctly, the values are correct in this function:

    public void AddUserToGroup(string userId, string groupName)
    {

        string ss = Password();
        bool bSuccess = false;

        try
        {
            using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, "lhw-nt.local", null, "lhw-nt\\administrator", ss))
            {
                GroupPrincipal group = GroupPrincipal.FindByIdentity(pc, groupName);
                group.Members.Add(pc, IdentityType.UserPrincipalName, userId);                 
                group.Save();

                bSuccess = true;
            }
        } catch (DirectoryServicesCOMException e)
        {
            MessageBox.Show(e.ToString(), "Fehler");
        }

        if(bSuccess)
        {
            MessageBox.Show("Erfolgreich", "Erfolg");
        }

When the user is in that group a principal error at

group.Members.Add(pc, IdentityType.UserPrincipalName, userId);

appears and won't go away even if the user is not in the group.

The error is:

System.DirectoryServices.AccountManagement.No Matching PrincipalException HResult=0x80131501 Message=Es wurde kein den angegebenen Parametern entsprechender Prinzipal gefunden. Source=System.DirectoryServices.AccountManagement StackTrace: at System.DirectoryServices.AccountManagement.PrincipalCollection.Add(PrincipalContext context, IdentityType identityType, String identityValue)

I already tried a try-catch block around that but the error still pops up. What is wrong?

c#
active-directory
userprincipal
asked on Stack Overflow May 29, 2020 by edvcoding • edited May 29, 2020 by edvcoding

2 Answers

0

That error is not because the user is already in the group. It truly does mean that the user could not be found.

In this line:

group.Members.Add(pc, IdentityType.UserPrincipalName, userId);  

You are telling it to match the userId to the UserPrincipalName. Does the value you are passing for userId match the user's UserPrincipalName? It should look something like username@lhw-nt.local. If you are passing just username, then you can change that line to have IdentityType.SamAccountName instead.

Once it can find the user and the user is already in the group, it will throw a PrincipalExistsException, which you can catch and even ignore if you'd like.


The rest of this answer is just a side note that you can ignore if you'd like.

I prefer to use the DirectoryServices namespace directly, which is what the AccountManagement namespace uses in the background anyway. It's a bit more code, but you have much more control over what happens. This often results in code that runs faster.

For example, here is an equivalent method to find the group and user by name and add the user to the group. This will not throw an exception if the user is already a member of the group. It will just silently continue.

You should handle the cases where either the group or user is not found. I have put comments in those spots.

public void AddUserToGroup(string userId, string groupName)
{

    string ss = Password();
    bool bSuccess = false;

    try
    {
        var searchRoot = new DirectoryEntry("LDAP://lhw-nt.local", "lhw-nt\\administrator", ss);

        //Find the group
        var groupSearcher = new DirectorySearcher
        {
            SearchRoot = searchRoot,
            //match group name by either sAMAccountName or cn
            Filter = $"(&(objectClass=group)(|(sAMAccountName={groupName})(cn={groupName})))",
            PropertiesToLoad = { "cn" } //if we omit this, it will load every attribute, which we don't need
        };

        var group = groupSearcher.FindOne()?.GetDirectoryEntry();

        if (group == null)
        {
            //group wasn't found
            return;
        }

        //Find the user
        var userSearcher = new DirectorySearcher
        {
            SearchRoot = searchRoot,
            Filter = $"(userPrincipalName={userId})",
            PropertiesToLoad = { "distinguishedName" }
        };

        var userDn = userSearcher.FindOne()?.Properties["distinguishedName"][0] as string;

        if (userDn == null)
        {
            //user wasn't found
            return;
        }

        //Add the user to the group
        group.Properties["member"].Add(userDn);
        group.CommitChanges();

        bSuccess = true;
    }
    catch (DirectoryServicesCOMException e)
    {
        MessageBox.Show(e.ToString(), "Fehler");
    }

    if (bSuccess)
    {
        MessageBox.Show("Erfolgreich", "Erfolg");
    }
}
answered on Stack Overflow May 29, 2020 by Gabriel Luci • edited May 29, 2020 by Gabriel Luci
0

Thanks for the answer... I will look into this in a few days, since we have other things to do in the moment, and I cannot test new code or our created tool. Once I had information, I will post them here.

answered on Stack Overflow Jun 8, 2020 by edvcoding

User contributions licensed under CC BY-SA 3.0