已经与其基础RCW分离的COM对象无法使用 - 为什么会发生?

emp*_*mpi 5 .net c# com interop active-directory

我有时会遇到以下异常:无法使用已与其基础RCW分离的COM对象

示例代码:

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(); 

} 
} 
Run Code Online (Sandbox Code Playgroud)

AdUser看起来像这样:

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; 
} 
} 
Run Code Online (Sandbox Code Playgroud)

这是我的代码的简化版本.有时会出现例外情况,有时则不会.大多数情况下,当我尝试设置UserAccountControl值时会发生这种情况.有谁知道可能是什么原因?

我发现当我处理AdEser创建的DirectoryEntry并且我仍在尝试使用AdUser对象时,会发生此错误.但是,上面发布的代码并非如此.DirectoryEntry可能以某种方式处置自己吗?

当我尝试在许多活动目录对象上执行操作时,我也得到此异常.例如,当我尝试为一千个用户设置SecurityDescriptor时,每200-300个用户就会收到此错误.当我在建立新连接后重试操作时,我不会得到例外.消息是检测到raceonrcwcleanup.我的应用程序不是多线程的.

任何帮助,将不胜感激.

emp*_*mpi 2

看来问题是由 AdUser 中的 NativeObject 创建 DirectoryEntry 引起的。当我将 AdUser 从以下位置更改为:

public class AdUser : DirectoryEntry 
{ 
public AdUser(DirectoryEntry entry) 
: base(entry.NativeObject) 
{ 
} 
} 
Run Code Online (Sandbox Code Playgroud)

并创建了将 DirectoryEntry 视为组件的包装器:

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) 
{ 
} 
} 
Run Code Online (Sandbox Code Playgroud)

然后我就不会收到这些错误了。更多详细信息请参见:http://directoryprogramming.net/forums/thread/7171.aspx