我在Outlook 2013中运行了一个旨在过滤垃圾邮件的插件。它查看传入的电子邮件,进行六次启发式搜索,如果其中的一到两个返回正数,则将邮件移至另一个文件夹进行检查;如果三个或三个以上的邮件被绊倒,它将永久删除邮件。
我的问题是它随机停止工作。加载项未标记为“禁用”或“无效”;它只是不再工作了。禁用它,然后再启用它可以使其恢复联机状态,然后可以正常工作,在刚刚失败的邮件上 include 。然后,它将在随后的一些消息中再次随机失败。据我所知,没有出现任何错误。没有异常被抛出。
我觉得这与Outlook的外接程序限制有关,因为它是(a)不确定的,并且(b)我检查的次数似乎更多。但是我所做的一切都不是很沉重。大多数情况只是检查电子邮件地址,主题和标题中的内容,或者在正文中查找关键短语。盯着它看,每条消息似乎都在不到一秒钟的时间内得到处理。我想第一个问题是,是否有办法查看Outlook对此的决策过程,即它正在跟踪的特定性能统计信息? (ETA:Outlook是在调用外接程序时还是在启动时强制执行其限制的?我所能找到的一切都仅涉及启动。)
似乎没有任何一项检查是负责任的;我已经逐一禁用了每个人,而且这种情况一直在发生。
这是中央代码。 SpamMarkerCheckList 是单个启发式检查的委托列表。 ClearAllMailMarkers()可以执行以下操作,例如将邮件标记为已读,将优先级设置为正常,删除所有标志等。 headers 是一个字典,其标题名称为键,字符串列表作为值。
private static void FilterInbox(object mailItem)
{
try
{
if (mailItem != null)
{
var mail = (Outlook.MailItem)mailItem;
var markers = SpamMarkersCount(mail, 3);
if (markers > 2)
{
PermanentlyDeleteEmail(mail);
}
else if (markers > 0)
{
ClearAllMailMarkers(mail);
mail.Move(_sequesteredFolder);
}
}
}
catch (Exception e)
{
MessageBox.Show("FilterSpam caught unexpected exception -- " + e);
}
}
private static int SpamMarkersCount(Outlook.MailItem mail, int threshold)
{
var spamMarkerCount = 0;
var headers = GetHeaderProperties(mail);
var emailAddressList = BuildAddressList(mail, headers);
var fullStringList = GetAllStrings(mail, headers);
foreach (var spamMarkerCheck in SpamMarkerCheckList)
{
if (spamMarkerCheck(mail, headers, emailAddressList, fullStringList))
{
spamMarkerCount++;
if (spamMarkerCount >= threshold)
{
return spamMarkerCount;
}
}
}
return spamMarkerCount;
}
我正在做的检查是:
答案 0 :(得分:0)
我建议您检查Windows事件查看器中特定于Outlook的记录。您的加载项很可能在运行时引发异常。
首先,Microsoft Office应用程序可以禁用行为异常的VSTO加载项。如果某个应用程序未加载VSTO加载项,则该应用程序可能被硬禁用或软禁用了VSTO加载项。
当VSTO加载项导致应用程序意外关闭时,可能会发生硬禁用。如果您在执行VSTO加载项中的Startup事件处理程序时停止调试器,则它也可能在开发计算机上发生。
当VSTO加载项产生不会导致应用程序意外关闭的错误时,可能会发生软件禁用。例如,如果在启动事件处理程序执行期间引发未处理的异常,则应用程序可能会软禁用VSTO加载项。
当您重新启用软禁用的VSTO加载项时,应用程序将立即尝试加载VSTO加载项。如果最初导致应用程序软禁用VSTO加载项的问题尚未解决,则应用程序将再次软禁用VSTO加载项。在How to: Re-enable a VSTO Add-in that has been disabled文章中了解有关此内容的更多信息。
其次,扩展了Outlook 2010,Outlook 2013和更高版本的加载项弹性指标,以监视加载项性能指标,例如加载项启动,关闭,文件夹切换,项目打开和调用频率。 Outlook会记录每个性能监视指标的经过时间(以毫秒为单位)。
例如,启动指标衡量Outlook启动期间每个连接的加载项所需的时间。然后,Outlook计算5次连续迭代中的启动时间中值。如果中值启动时间超过1000毫秒(1秒),则Outlook将禁用该加载项,并向用户显示一个通知,指出该加载项已被禁用。用户可以选择始终启用该加载项,在这种情况下,即使加载项超过了1000毫秒的性能阈值,Outlook也不会禁用该加载项。在Performance criteria for keeping add-ins enabled部分中了解有关此内容的更多信息。
您可能会发现Outlook’s slow add-ins resiliency logic and how to always enable slow add-ins文章很有帮助。
最后,Outlook使用单线程单元模型,并可能通过在运行时引发异常来防止来自辅助线程的任何调用。您应该仅在主线程上使用OOM。如果需要在后台进行任何处理,则可以考虑提取所需的纯数据并将其传递进行处理。扩展MAPI还允许运行辅助线程。
答案 1 :(得分:0)
我找到了最直接的原因:垃圾回收。在调试器中运行了一段时间之后,我注意到该加载项在GC事件发生后立即停止了工作。多次运行表明,这种情况持续发生。
最终的原因是我如何将函数与文件夹相关联:
private static Outlook.Account emailStore; // outside ThisAddIn_Startup
[...]
emailStore.DeliveryStore.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox).Items.ItemAdd += FilterInbox;
出于我不完全理解的原因,这会在GC后导致问题,但这不是:
private static Outlook.Items emailItems; // outside ThisAddIn_Startup
[...]
emailItems = emailStore.DeliveryStore.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox).Items;
emailItems.ItemAdd += FilterInbox;
我明白为什么将它设置为静态是至关重要的,但是我不明白为什么它会使分配有所不同。凡是对C#对象有更深刻理解并可以解释的人,我都想听听。