0

I am trying to get extra user information from AD.

  List<string> allUsers = new List<string>();
            PrincipalContext ctx2 = new PrincipalContext(ContextType.Domain, "FUNDACION", valor);     
            UserPrincipal qbeUser2 = new UserPrincipal(ctx2);

            qbeUser2.Enabled = true; // activo para autenticacion

            PrincipalSearcher srch2 = new PrincipalSearcher(qbeUser2);
            srch2.QueryFilter = qbeUser2;

           DirectoryEntry dirEntry = (qbeUser2.GetUnderlyingObject() as DirectoryEntry);  

I am getting an exception at this line :

DirectoryEntry dirEntry = (qbeUser2.GetUnderlyingObject() as DirectoryEntry);

An exception of type 'System.InvalidOperationException' occurred in System.DirectoryServices.AccountManagement.dll but was not handled in user code Additional information: The Principal object must be persisted before this method can be called.

Ivan Diaz Salas
  • 309
  • 1
  • 9
  • 25

3 Answers3

1

You need to execute qbeUser2.Save() before you can call to GetUnderlyingObject()

Kostia Shiian
  • 1,024
  • 7
  • 12
0

Do you have access to the source code of UserPrincipal class, and specifically to its GetUnderlyingObject() method?

It looks like the method is throwing an exception. This might be happening by contract or by accident.

If it is expected to throw this exception ("by contract"), then you should wrap this method call inside a try/catch block and handle the exception accordingly:

try {
    DirectoryEntry dirEntry = (qbeUser2.GetUnderlyingObject() as DirectoryEntry);
} catch (InvalidOperationException e) {
    // handle expected exception accordingly
}

Otherwise, you should make sure the object is persisted before calling the method, just as the exception message says (docs here):

qbeUser2.Save();
DirectoryEntry dirEntry = (qbeUser2.GetUnderlyingObject() as DirectoryEntry);
heltonbiker
  • 26,657
  • 28
  • 137
  • 252
  • How do i know if the object is persisted? the Principal Object is just created before the method is called. – Ivan Diaz Salas May 25 '15 at 17:32
  • If it is just created, then it is probably not persisted yet, since it lives only in memory. You should call some routine to persist it, but which routine would be, only you could know (or at least _should_ know). Who writes this DLL you are using? – heltonbiker May 25 '15 at 17:40
  • http://stackoverflow.com/questions/3929561/how-to-get-active-directory-attributes-not-represented-by-the-userprincipal-clas – Ivan Diaz Salas May 25 '15 at 17:45
  • "Do you have access to the source code of UserPrincipal class, and specifically to its GetUnderlyingObject() method?", unfortunately [`System.DirectoryServices.AccountManagement.UserPrincipal`](https://msdn.microsoft.com/en-us/library/system.directoryservices.accountmanagement.userprincipal(v=vs.110).aspx) is not on the [Refrence Source](http://referencesource.microsoft.com/#q=System.DirectoryServices.AccountManagement) – Scott Chamberlain May 25 '15 at 18:02
  • Well, I didn't know this was a .NET assembly. A quick search revealed the object has a `Save()` method, and I edited my answer, adding a link to the docs. – heltonbiker May 25 '15 at 18:36
0

Try this buddy:

Principal resultFind = searcher.FindOne();
DirectoryEntry dirEntry = (resultFind.GetUnderlyingObject() as DirectoryEntry);
// CODE HERE

or

foreach (Principal result in searcher.FindAll()){
    DirectoryEntry directoryEntry = result.GetUnderlyingObject() as DirectoryEntry;
    // CODE HERE
}

See this example:

PrincipalContext CompanyPrincipalContext([Optional] string directoryOU)
{
    string pw = "password";
    PrincipalContext principalContext = new PrincipalContext(ContextType.Domain, "domain.com.br", directoryOU, ContextOptions.Negotiate | ContextOptions.Signing | ContextOptions.Sealing, @"domain.com.br\userWithPrivilege", pw);
    return principalContext;
}

And

public List<string> FindSamAccountNames(string name)
{
    try
    {
        List<string> samaccountnames = new List<string>();

        using (PrincipalContext principalContext = CompanyPrincipalContext())
        {
            UserPrincipal user = new UserPrincipal(principalContext);
            PrincipalSearcher searcher = new PrincipalSearcher(user);

            user.Name = "*" + name + "*";

            searcher.QueryFilter = user;

            foreach (Principal result in searcher.FindAll())
            {
                DirectoryEntry directoryEntry = result.GetUnderlyingObject() as DirectoryEntry;
                samaccountnames.Add(result.Name);
                samaccountnames.Add(directoryEntry.Properties["samAccountName"].Value.ToString());
            }

            return samaccountnames;
        }
    }
    catch (Exception)
    {
        throw;
    }
}