System.Runtime.InteropServices.COMException (0x80030020): 操作失败

System.Runtime.InteropServices.COMException (0x80030020): The operation failed

我正在尝试使用以下方法将 Outlook.MailItem 保存到文件夹:

MailItem.SaveAs(path, Outlook.OlSaveAsType.olMSG)

这在大多数情况下都可以正常工作。但是,当大约有 20 封电子邮件同时发送到 Outlook 时,对于其中的一些,我得到以下异常:

System.Runtime.InteropServices.COMException (0x80030020): The operation failed.
   at Microsoft.Office.Interop.Outlook._MailItem.SaveAs(String Path, Object Type)

我检查了代码 0x80030020 似乎是 "A share violation has occurred." 的意思,但是我不确定它是什么意思。在我的应用程序中,我有以下两行,第一行将电子邮件保存到一个文件夹,第二行尝试将该文件 POST 保存到 API:

file = MailItemHelper.SaveMailItemToOFEFolder(mailItem);
bool isEmailSentByHttp = MailItemHelper.SendMailItemToOFEApi(_userid, file)

该路径包含电子邮件的主题,通过执行以下操作清理以删除非字母数字字符:

Regex nonAlphaNumericRgx = new Regex(@"\W|_");
subject = nonAlphaNumericRgx.Replace(mail.Subject, "_");

我想我不能直接说出问题是什么,但我可以尝试给你一些提示。

根据 MS documentation,Outlook 似乎正在使用 StgOpenStorage 函数,抛出 STG_E_SHAREVIOLATION 错误:

Access denied because another caller has the file open and locked.

这意味着 Outlook 搞砸了(用户点击了 "message" 并且 outlooks 锁定了文件,或者其他什么)或者可能在用你的正则表达式更改文件名后你的字符串最终是与另一个文件相同,而它正在写入另一个文件。

您如何连接到 Outlook?您的应用程序是否在收到每封邮件时使用一个新线程?您可以添加一个 log4net 并在您的代码中记录所有操作,例如:

// receive and email and store subject name on var subject
log.Info($"E mail with subject '{subject}' arrived.");
// convert name and save on var newSubject
log.Info($"Mail will be saved as '{newSubject}'.");
// notify the beginning of the operation
log.Info("Calling MailItemHelper.SaveMailItemToOFEFolder.");
// notify the end of the operation
log.Info("Mail saved successfully.");
// notify Post in REST API
log.Info("Sending in MailItemHelper.SendMailItemToOFEApi");
// notify end of Post in REST API
log.Info("MailItemHelper.SendMailItemToOFEApi sent");

这将清楚地了解所有邮件是如何被检索的,如果有一些线程问题,您可以先检查哪些是 finishing/starting。