Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
291 views
in Technique[技术] by (71.8m points)

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

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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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;
    } 
    ...
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...