当代码尝试保存邮件项目时,Outlook 互操作代码第二次抛出 "message has been changed" 错误
Outlook interop code throws "message has been changed" error the second time when the code tries to save a mail item
首先,这个问题只发生在少数客户端机器上,我无法在我的任何测试机器上复制它。
所以我在LINQPad中有如下测试代码:
var application = new Application();
var session = application.Session;
const string entryId = "arbitrary entry ID";
const string propertyName = "http://schemas.microsoft.com/mapi/string/{31A9B8DA-D4A0-4B96-87AE-01D6E9BCFCCE}/Test/0x0000001F";
// Save test property for the first time.
var mail = (MailItem)session.GetItemFromID(entryId);
var propertyAccessor = mail.PropertyAccessor;
propertyAccessor.SetProperty(propertyName, 1);
mail.Save();
Marshal.ReleaseComObject(propertyAccessor);
Marshal.ReleaseComObject(mail);
// Save test property for the second time.
mail = (MailItem)session.GetItemFromID(entryId);
var propertyAccessor = mail.PropertyAccessor;
propertyAccessor.SetProperty(propertyName, 2);
mail.Save();
Marshal.ReleaseComObject(propertyAccessor);
Marshal.ReleaseComObject(mail);
Marshal.ReleaseComObject(session);
Marshal.ReleaseComObject(application);
第二个 mail.Save()
调用在这几台客户端机器上有 100% 的抛出异常:System.Runtime.InteropServices.COMException (0x80040109): The operation cannot be performed because the message has been changed.
由于上述代码正确释放了第一个 mail
对象并再次使用条目 ID 检索第二个 mail
对象。在第二次检索对象和调用其 Save()
方法之间更改 mail
对象的机会非常低,更不用说 100% 的可重现率了。
我只能认为它看起来像是 Outlook 中的一个错误,它可能会在任何东西调用一次 Save()
方法后立即将邮件对象永久标记为已更改。
有人知道是否有解决方法吗?
这些机器使用的是最新版本的 Office 2016。
IMAP4 是最差的之一 - 每次您尝试触摸任何存储对象时,它都会尝试同步。您可以尝试绕过 IMAP4 层并直接转到用作底层本地存储的 PST 提供程序。在扩展 MAPI(C++ 或 Delphi)中,您可以使用 IProxyStoreObject interface. In case of languages other than C++ or Delphi, you can use Redemption (I am its author) and its RDOSession.Stores.UnwrapStore
method - the message can be then opened from the unwrapped store using RDOStore.GetMessageFromID
.
首先,这个问题只发生在少数客户端机器上,我无法在我的任何测试机器上复制它。
所以我在LINQPad中有如下测试代码:
var application = new Application();
var session = application.Session;
const string entryId = "arbitrary entry ID";
const string propertyName = "http://schemas.microsoft.com/mapi/string/{31A9B8DA-D4A0-4B96-87AE-01D6E9BCFCCE}/Test/0x0000001F";
// Save test property for the first time.
var mail = (MailItem)session.GetItemFromID(entryId);
var propertyAccessor = mail.PropertyAccessor;
propertyAccessor.SetProperty(propertyName, 1);
mail.Save();
Marshal.ReleaseComObject(propertyAccessor);
Marshal.ReleaseComObject(mail);
// Save test property for the second time.
mail = (MailItem)session.GetItemFromID(entryId);
var propertyAccessor = mail.PropertyAccessor;
propertyAccessor.SetProperty(propertyName, 2);
mail.Save();
Marshal.ReleaseComObject(propertyAccessor);
Marshal.ReleaseComObject(mail);
Marshal.ReleaseComObject(session);
Marshal.ReleaseComObject(application);
第二个 mail.Save()
调用在这几台客户端机器上有 100% 的抛出异常:System.Runtime.InteropServices.COMException (0x80040109): The operation cannot be performed because the message has been changed.
由于上述代码正确释放了第一个 mail
对象并再次使用条目 ID 检索第二个 mail
对象。在第二次检索对象和调用其 Save()
方法之间更改 mail
对象的机会非常低,更不用说 100% 的可重现率了。
我只能认为它看起来像是 Outlook 中的一个错误,它可能会在任何东西调用一次 Save()
方法后立即将邮件对象永久标记为已更改。
有人知道是否有解决方法吗?
这些机器使用的是最新版本的 Office 2016。
IMAP4 是最差的之一 - 每次您尝试触摸任何存储对象时,它都会尝试同步。您可以尝试绕过 IMAP4 层并直接转到用作底层本地存储的 PST 提供程序。在扩展 MAPI(C++ 或 Delphi)中,您可以使用 IProxyStoreObject interface. In case of languages other than C++ or Delphi, you can use Redemption (I am its author) and its RDOSession.Stores.UnwrapStore
method - the message can be then opened from the unwrapped store using RDOStore.GetMessageFromID
.