Outlook VSTO 插件在遍历默认联系人文件夹中的联系人时停止执行
Outlook VSTO plugin stops executing while iterating over contacts in default contacts folder
我编写了一个 Outlook 插件,其中一种方法通过在默认联系人文件夹中搜索具有指定电子邮件地址的联系人来搜索联系人的 phone 号码。
对于我的某些 outlook 用户,下面示例中的 for 循环似乎只是停止了 运行。
"processing contact" 消息是最后记录的消息,"Iteration completed" 消息从未出现。
此外,似乎没有发生异常(我现在无法在开发盒上测试它,我依赖于我记录的调试消息),该方法似乎只是在 for 循环中停止并且调用下面方法的方法不会继续执行。
var phoneNumbers = new List<PhoneNumberModel>();
var mailAddress = "findme@incontacts.com";
var contacts = Application.ActiveExplorer().Session.GetDefaultFolder(OlDefaultFolders.olFolderContacts);
if(contacts != null)
{
logger.Debug($"Iterating contact items...");
foreach (ContactItem foundContact in contacts.Items)
{
logger.Debug("Processing contact: {contact.CompanyAndFullName}");
if ((foundContact.Email1Address?.ToLower() ?? "").Contains(mailAddress.ToLower()))
{
if (!string.IsNullOrWhiteSpace(foundContact.BusinessTelephoneNumber))
{
phoneNumbers.Add(new PhoneNumberModel { NumberType = "Business phone number", PhoneNumber = foundContact.BusinessTelephoneNumber });
}
}
logger.Debug($"AddPhoneNumbersFromDefaultAddressBook() Iteration completed");
}
}
我怀疑 API 某种超时,所以我将对上述方法的调用包装在超时处理程序中:
int timeout = 1000;
var task = SomeOperationAsync();
if (await Task.WhenAny(task, Task.Delay(timeout)) == task) {
// task completed within timeout
} else {
// timeout-logic
}
// further-logic
超时逻辑和进一步逻辑不执行。
知道这里会发生什么吗?
您的代码假定联系人文件夹中只能有 ContactItem
个对象。如果你有一个 DistItem
对象,它将失败。
另请记住,您无法在辅助线程(例如 Task
对象使用的线程)上访问 Outlook 对象模型。只能从辅助线程访问扩展 MAPI 对象,但这需要扩展 MAPI。如果使用 Redemption (I am its author) is an option, is RDO 对象系列包装扩展 MAPI 并且可以从辅助线程访问。
第三,永远不要遍历文件夹中的所有项目,让 Items.Find/FindNext
或 Items.Restrict
来完成繁重的工作。在您的特定情况下,该查询可能必须类似于 [Email1Address] = 'user@site.demo'
我编写了一个 Outlook 插件,其中一种方法通过在默认联系人文件夹中搜索具有指定电子邮件地址的联系人来搜索联系人的 phone 号码。
对于我的某些 outlook 用户,下面示例中的 for 循环似乎只是停止了 运行。 "processing contact" 消息是最后记录的消息,"Iteration completed" 消息从未出现。
此外,似乎没有发生异常(我现在无法在开发盒上测试它,我依赖于我记录的调试消息),该方法似乎只是在 for 循环中停止并且调用下面方法的方法不会继续执行。
var phoneNumbers = new List<PhoneNumberModel>();
var mailAddress = "findme@incontacts.com";
var contacts = Application.ActiveExplorer().Session.GetDefaultFolder(OlDefaultFolders.olFolderContacts);
if(contacts != null)
{
logger.Debug($"Iterating contact items...");
foreach (ContactItem foundContact in contacts.Items)
{
logger.Debug("Processing contact: {contact.CompanyAndFullName}");
if ((foundContact.Email1Address?.ToLower() ?? "").Contains(mailAddress.ToLower()))
{
if (!string.IsNullOrWhiteSpace(foundContact.BusinessTelephoneNumber))
{
phoneNumbers.Add(new PhoneNumberModel { NumberType = "Business phone number", PhoneNumber = foundContact.BusinessTelephoneNumber });
}
}
logger.Debug($"AddPhoneNumbersFromDefaultAddressBook() Iteration completed");
}
}
我怀疑 API 某种超时,所以我将对上述方法的调用包装在超时处理程序中:
int timeout = 1000;
var task = SomeOperationAsync();
if (await Task.WhenAny(task, Task.Delay(timeout)) == task) {
// task completed within timeout
} else {
// timeout-logic
}
// further-logic
超时逻辑和进一步逻辑不执行。
知道这里会发生什么吗?
您的代码假定联系人文件夹中只能有 ContactItem
个对象。如果你有一个 DistItem
对象,它将失败。
另请记住,您无法在辅助线程(例如 Task
对象使用的线程)上访问 Outlook 对象模型。只能从辅助线程访问扩展 MAPI 对象,但这需要扩展 MAPI。如果使用 Redemption (I am its author) is an option, is RDO 对象系列包装扩展 MAPI 并且可以从辅助线程访问。
第三,永远不要遍历文件夹中的所有项目,让 Items.Find/FindNext
或 Items.Restrict
来完成繁重的工作。在您的特定情况下,该查询可能必须类似于 [Email1Address] = 'user@site.demo'