2017-05-10 2 views
1

Ich versuche, den Inhalt des relativ großen Öffentlichen Ordner-Layouts (mehrere 000 Ordner) meines Unternehmens aus Exchange Server 2010 mit RDO 5.14 zu exportieren.Verwenden von RDO/MAPI zum Extrahieren großer Informationsspeicher für Öffentliche Ordner und Abrufen von E_MAPI_TOO_BIG

Ich treffe das Problem, das viele Leute finden, in dem Exchange 2010 irgendwann den Fehler E_MAPI_TOO_BIG gibt, weil der Benutzer, den ich benutze, die Exchange-Speichergrenzen documented here verletzt hat.

Die akzeptierte Lösung in vielen Fällen ist while (Marshal.ReleaseComObject(ref)>0) auf jedem ref anrufen und GC.Collect() einmal in einer Weile, die der Verarbeitung von mehr Elementen zu ermöglichen, scheint aber immer noch nicht erlaubt, mich in mehr als 500 Meldungen zu erhalten.

Einige spielen mit dem Code herum. Es zeigt die folgende überraschende Tatsache (zumindest für mich).

Wenn ich über die Elemente in einem Ordner wie dieses iterieren ist es kein Problem:

for (int i = 1; i < items.Count; ++i) { 
    IRDOMail item = items.Item(i); 
    string SUCCESS = item.EntryID; 
} 

ABER, wenn ich irgendwann dieses Codebeispiel verwenden Sie es (an anderer Stelle im Code nicht versuchen, andere Ordner zuzugreifen) mit E_MAPI_TOO_BIG:

for (int i = 1; i < items.Count; ++i) { 
    IRDOMail item = items.Item(i); 
    string FAIL = item.Subject; 
} 

an dieser Stelle habe ich die sehr Grenze meiner COM Fähigkeiten erreicht. Es deutet darauf hin, dass ein Teil des Aufhebens einer COM-Eigenschaft eines MailItem in .NET InterOp einen Verweis aufgreift, den ich nicht freigeben kann. Wenn das der Fall ist, bin ich mir nicht sicher, wie ich es beheben kann, wenn überhaupt?

Ähnliches (aber unterschiedliches) Verhalten kann man sehen, wenn ich MAPI ohne RDO verwende, was darauf hindeutet, dass es eine Eigenart von MAPI (14.0) ist?

Antwort

1

Dies erwies sich als ein Problem mit Programmstruktur zu sein und nicht eine direkte Ausgabe entweder mit RDO oder MAPI. Insbesondere versucht das Problem, die gesamte Struktur und Elemente rekursiv zu verarbeiten.

Es scheint, als ob der Zugriff auf eine Eigenschaft eines MAPI/RDO-MailItem aus dem Ordner eine interne Referenz aus dem Ordner zurück auf das Element erstellt. Obwohl ich mir nicht sicher bin, ob das stimmt oder wie man es verifiziert.

Daher, wenn ein Unterzweig (nicht nur ein Ordner) der Struktur mehr als 500 Nachrichten enthält, würden Sie E_MAPI_TOO_BIG versuchen, die Struktur in der beschriebenen Weise zu "besuchen".

Die Lösung ist dann Rekursion zu verwenden, um eine Liste der Ordner EntryId zu erstellen und dann über diese Liste mit GetFolderFromId() zu iterieren, um den Ordner zu erhalten und dann über die Elemente zu iterieren. Keine der MAPI/RDO-Programmierungsressourcen, die ich bisher gefunden habe, erwähnt diese Tatsache.

UPDATE

Nach mehr Zeit damit verbringen, MAPI zu bekommen in verwaltetem Code arbeiten hat mich zu dem Schluss gekommen, dass es sich um eine grundsätzlich eine schlechte Idee ist, zu versuchen und zu tun, was ich versuche. Während die obige Lösung mich ein wenig weiter brachte, scheiterte sie letztendlich wieder (mit demselben Fehler), als ich versuchte, auf weitere Eigenschaften der Nachricht zuzugreifen.

Im Nachhinein scheint das Problem zu sein, dass es sehr nah funktioniert und eine Menge Leute haben es geschafft, damit auskommen, daher gibt es eine Menge Ressourcen online dies zu demonstrieren. Aber da MAPI in verwaltetem Code nicht von Microsoft unterstützt wird, scheint es, dass wir uns zunächst auf wackeligen Beinen befinden. Auch wenn dies eher COM Interop als direktes MAPI ist.

Alles, was mit Exchange skaliert werden muss, erfordert meiner Meinung nach eine der anderen Exchange-Technologien. Ich verwendete schließlich EWS, das vollständig und vor allem zuverlässig erscheint. Ich hoffe, das hilft jemandem!

+0

Sie müssen nur sehr vorsichtig mit hängenden Referenzen sein, und besonders vermeiden, Mehrfachnotation zu verwenden. –

0

Sie müssen ReleaseComObject verwenden:

for (int i = 1; i < items.Count; ++i) { 
    IRDOMail item = items.Item(i); 
    string FAIL = item.Subject; 
    Marshal.ReleaseComObject(item); 
} 
+0

Dies scheint keinen Unterschied zu machen. Vermutlich reicht das "Objekt" aus, um den Verweis freizugeben? Ich habe verschiedene Referenzen im Netz gefunden, die das Hinzufügen von Marshal.ReleaseComObject() empfehlen, aber das einzige Mal, dass ich es für notwendig halte, ist, wenn die Referenz zu lange im Bereich bleibt, was während einer rekursiven Ordnerüberquerung oder ähnlichem der Fall sein kann. Was hier nicht der genaue Fall ist. –

Verwandte Themen