COM object that has been separated from its underlying RCW can not be used - why does it happen?

15,171

Solution 1

It seems that the problem is caused by creating DirectoryEntry from NativeObject in AdUser. When I changed AdUser from:

public class AdUser : DirectoryEntry 
{ 
public AdUser(DirectoryEntry entry) 
: base(entry.NativeObject) 
{ 
} 
} 

And created wrapper that treats DirectoryEntry as a component:

public class ActiveDirectoryObject : IDisposable 
{ 
private bool disposed; 
public DirectoryEntry Entry { get; protected set; } 

public ActiveDirectoryObject(DirectoryEntry entry) 
{ 
Entry = entry; 
} 

public void CommitChanges() 
{ 
Entry.CommitChanges(); 
} 

public void Dispose() 
{ 
Dispose(true); 
GC.SuppressFinalize(this); 
} 

private void Dispose(bool disposing) 
{ 
if (!this.disposed) 
{ 
if (disposing) 
{ 
if (Entry != null) Entry.Dispose(); 
} 
disposed = true; 
} 
} 
} 

public class AdUser : ActiveDirectoryObject 
{ 
public AdUser(DirectoryEntry entry) 
: base(entry) 
{ 
} 
} 

Then I don't get these errors. Further details here: http://directoryprogramming.net/forums/thread/7171.aspx

Solution 2

Yes, it is possible that DirectoryEntry object is disposed due to the garbage collection. GC is running in its own thread, so race on RCW cleanup is possible.

Try to save reference to it in your AdUser object. I.e. it should looks like

public class AdUser : DirectoryEntry 
{ 
  DirectoryEntry entry;
    public AdUser(DirectoryEntry entry) : base(entry.NativeObject) 
    { 
      this.entry = entry;
    } 
    ...
}
Share:
15,171
coopejoh
Author by

coopejoh

Updated on June 04, 2022

Comments

  • coopejoh
    coopejoh almost 2 years

    I sometimes get the following exception: COM object that has been separated from its underlying RCW can not be used

    Sample code:

    using (AdOrganizationalUnit organizationalUnit = new AdOrganizationalUnit(ADHelper.GetDirectoryEntry(ouAdDn))) 
    { 
    using (AdUser user = organizationalUnit.AddUser(commonName)) 
    { 
    //set some properties 
    user.Properties[key].Add(value); 
    
    user.CommitChanges(); 
    
    user.SetPassword(password); //it is set using Invoke 
    
    //must be set after creating user 
    user.Properties["UserAccountControl"].Value = 512; 
    
    user.CommitChanges(); 
    
    } 
    } 
    

    AdUser looks like this:

    public class AdUser : DirectoryEntry 
    { 
    public AdUser(DirectoryEntry entry) 
    : base(entry.NativeObject) 
    { 
    } 
    
    public bool SetPassword(string password) 
    { 
    object result = this.Invoke("SetPassword", new object[] { password }); 
    return true; 
    } 
    } 
    

    This is simplified version of my code. The exception sometimes shows up, sometimes not. Most of the time it happens when I'm trying to set UserAccountControl value. Does anyone know what could be the reason?

    I found out that this error happens when I dispose DirectoryEntry the AdUser was created with and I'm still trying to use AdUser object. However this is not the case in the code posted above. Is it possible that DirectoryEntry somehow disposes itself?

    I also get this exception when I try to execute operation on many active directory objects. For example when I try to set SecurityDescriptor for one thousand users, I get this error every 200-300 users. When I retry operation after establishing new connections I don't get exception. The message is raceonrcwcleanup was detected. My app is not multithreaded.

    Any help would be appreciated.

  • coopejoh
    coopejoh over 14 years
    Sorry for no response, I tried to use DirectoryEntry as component and currently it works ok. Further details: directoryprogramming.net/forums/thread/7171.aspx
  • awe
    awe over 14 years
    @empi: You should copy the answer from the post you refer to and add it here as asnwer to your own question. Then mark that as the answer. That would help others looking for answers here. It is less visible when you just post a link in a comment...
  • Drew Chapin
    Drew Chapin about 10 years
    +1 for solving your own question, posting the solution, and more importantly solving the exact same problem I came here for.