2009-09-29 2 views
5

volte ottengo la seguente eccezione: oggetto COM che è stato separato dal suo RCW sottostante non può essere utilizzatoL'oggetto COM che è stato separato dal relativo RCW sottostante non può essere utilizzato: perché succede?

codice di esempio:

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 assomiglia a questo:

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

Questa è la versione semplificata del mio codice. L'eccezione a volte compare, a volte no. Il più delle volte succede quando sto cercando di impostare il valore di UserAccountControl. Qualcuno sa quale potrebbe essere la ragione?

Ho scoperto che questo errore si verifica quando dispongo DirectoryEntry con cui è stato creato AdUser e sto ancora tentando di utilizzare l'oggetto AdUser. Tuttavia questo non è il caso nel codice pubblicato sopra. È possibile che DirectoryEntry si adatti in qualche modo?

Ho anche questa eccezione quando provo a eseguire l'operazione su molti oggetti di directory attivi. Ad esempio, quando provo a impostare SecurityDescriptor per mille utenti, ottengo questo errore ogni 200-300 utenti. Quando riprovo l'operazione dopo aver stabilito nuove connessioni, non ottengo eccezioni. Il messaggio è stato rilevato raceonrcwcleanup. La mia app non è multithread.

Qualsiasi aiuto sarebbe apprezzato.

risposta

2

Sembra che il problema è causato da creando DirectoryEntry da NativeObject in ADUser. Quando ho cambiato ADUser da:

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

e ha creato wrapper che tratta DirectoryEntry come componente:

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) 
{ 
} 
} 

Allora io non capisco questi errori. Ulteriori dettagli: http://directoryprogramming.net/forums/thread/7171.aspx

+0

** + 1 ** per risolvere la propria domanda, postare la soluzione e, soprattutto, risolvere esattamente lo stesso problema per cui sono venuto qui. –

3

Sì, è possibile che l'oggetto DirectoryEntry venga eliminato a causa della garbage collection. GC è in esecuzione nella sua stessa thread, quindi è possibile correre su RCW cleanup.

Provare a salvare il riferimento ad esso nell'oggetto AdUser. Cioè dovrebbe sembra

public class AdUser : DirectoryEntry 
{ 
    DirectoryEntry entry; 
    public AdUser(DirectoryEntry entry) : base(entry.NativeObject) 
    { 
     this.entry = entry; 
    } 
    ... 
} 
+0

Scusate per nessuna risposta, ho provato a utilizzare DirectoryEntry come componente e attualmente funziona correttamente. Ulteriori dettagli: http://directoryprogramming.net/forums/thread/7171.aspx – empi

+0

Ok, sono contento che il problema sia risolto –

+0

@empi: dovresti copiare la risposta dal post a cui fai riferimento e aggiungerla qui come la tua domanda Quindi segnalo come risposta. Ciò aiuterebbe gli altri a cercare risposte qui. È meno visibile quando si pubblica un link in un commento ... – awe