在Outlook中处理大量邮件

3

Outlook插件逐一打开大量(>100)邮件,保存邮件正文并进一步处理。

foreach (MailItemContainer mc in Mails)
{
     var inspector = mc.MailItem.GetInspector;
     var document = (Document)inspector.WordEditor; 
     document.SaveAs(tempFilePath, format);

     Process(tempFilePath);

     //dispose inspector
     Marshal.ReleaseComObject(inspector);
     Marshal.ReleaseComObject(document);
     inspector = null;
     document = null;
     Marshal.ReleaseComObject(mc.MailItem);
     mc.MailItem = null;
}

然而,经过一些处理(通常在80个项目左右),异常开始出现。

 System.Runtime.InteropServices.COMException (0xC4104005): Operation failed.
     in Microsoft.Office.Interop.Outlook._MailItem.get_GetInspector()

通过Marshal.Release/FinalReleaseComObject释放检查器和文档并不能解决问题。需要使用以下方法关闭检查器:

 ((_Inspector)inspector).Close(OlInspectorClose.olDiscard);

出现奇怪的行为:从列表中的第二个项目开始,document.SaveAs会保存该项的副本,即使从中获取了正确的xml的项的inspector。

在Outlook中处理多个项目的正确方法是什么?是否需要以某种特殊方式处理检查员?

更新2:

释放邮件项后,我收到“当前进程已使用其窗口管理器对象的系统允许句柄”。使用MailItem.Close(OlInspectorClose.olDiscard)会导致Outlook崩溃。


顺便问一下,为什么你需要使用一个文字编辑器? - Eugene Astafiev
两个原因。一是处理选择,二是将其转换为带有适当编码支持的HTML(MailItem.SaveAs无法正确处理某些代码页)。 - Anatoly Sazanov
2个回答

1
通过Marshal.Release/FinalReleaseComObject释放检查员和文档并没有帮助。你需要立即释放所有底层COM对象,而不只是其中一些。在使用完Outlook对象后,请使用System.Runtime.InteropServices.Marshal.ReleaseComObject来释放它。然后在Visual Basic中将变量设置为Nothing(在C#中为null)以释放对该对象的引用。您可以在Systematically Releasing Objects文章中了解更多信息。

我已经尝试过了,但在同一点上仍然遇到了许多其他异常。这就是为什么我询问如何处理 Outlook 检查器的方式,当您连续打开数百个检查器以选择每封邮件时。 - Anatoly Sazanov
我已经更新了我的答案。还尝试了nullifying+GC.Collect。所有操作都发生在主VSTO线程上。 - Anatoly Sazanov
我没有看到你释放所有对象的完整代码。 - Eugene Astafiev
我忘记了邮件项本身。在释放/置空它之后,我仍然无法处理合理数量的项目。看起来检查器仍然保持打开状态,而我无法关闭它们。 - Anatoly Sazanov
我不知道你在代码中具体在做什么。但是你没有立即释放代码中所有的基础COM对象,这导致了问题的出现。 - Eugene Astafiev
显示剩余2条评论

0

我曾经遇到过与 Outlook.Inspector 相同的问题,

解决方法是:您需要在 Outlook.Inspector 上调用 Close 方法,并使用 OlInspectorClose.olDiscard 参数...

我之前只是将其设置为 null,但没有起到帮助作用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接