坚持了 2 个多月才能使 Outlook 插件正常工作
Stuck for over 2 months getting an outlook addin to work
这基本上是对上一个问题的重新post,但我已经在同一问题上停留了 2 个多月,但没有取得任何进展。长话短说,有时它会触发,有时它不会。有时它加载一次,有时 Outlook 将其默认为 "inactive",我似乎无能为力。当它确实触发时,它会在尝试发送第一封电子邮件时挂断。因此,我在检查的日期范围之外有旧约会,并且会为这些约会显示消息框。当它到达 "new" 个约会(在日期范围内)时,有时它会弹出第一个消息框,但会在尝试发送电子邮件时挂断。有时,第一个 "good" 消息框无法弹出。我得到的关于这个问题的最后建议是建立一个日志文件,但我不知道 how/what 它对我有什么好处,或者老实说,我什至不确定我需要记录什么,当我询问时,提出它的那位先生从未回答过我。预先感谢您的帮助,这很容易成为我作为开发人员 运行 遇到过的最令人沮丧的事情之一。
using System;
using System.Threading;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using Outlook = Microsoft.Office.Interop.Outlook;
using Office = Microsoft.Office.Core;
using Microsoft.Office.Interop.Outlook;
using System.Windows.Forms;
namespace OutlookAddIn1
{
public partial class ThisAddIn
{
//Outlook.Inspectors inspectors;
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
doStuff();
}
private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
{
}
#region VSTO generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InternalStartup()
{
this.Startup += new System.EventHandler(ThisAddIn_Startup);
this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
}
//https://msdn.microsoft.com/en-us/library/ms268866.aspx
private void doStuff()
{
Outlook.Application app = new Outlook.Application();
Thread.Sleep(30000); //120 seconds - was 120000
DateTime firstRun = DateTime.Now; //So we can check every 24 hours? Maybe once initially as well.
DateTime lastRun = DateTime.Now;//.AddHours(1); //We're going to compare this to firstRun
bool whileTrue = true;
//int test = 0;
try
{
while (whileTrue)
{
if (whileTrue == true)//(firstRun > lastRun.AddDays(1))
{
Outlook.MAPIFolder calendarFolder = Application.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderCalendar);
Outlook.Items outlookCalendarItems = calendarFolder.Items;
outlookCalendarItems.IncludeRecurrences = true; //was true
List<Outlook.AppointmentItem> lst = new List<Outlook.AppointmentItem>();
foreach (Outlook.AppointmentItem item in outlookCalendarItems)
{
lst.Add(item);
//We can probably just handle logic in here without the second for loop that comes next
}
foreach (Outlook.AppointmentItem x in lst)
{
DateTime startDate = DateTime.Now.AddDays(1);
DateTime endDate = DateTime.Now.AddDays(5);
DateTime apptDate = x.Start;
if (x.Subject.ToLower().Contains("telos"))
{
MessageBox.Show("X: " + x.Start + "XYZ: " + x.Subject);
if (x.Start > startDate && x.Start < endDate)
{
Microsoft.Office.Interop.Outlook.MailItem email = app.CreateItem((OlItemType.olMailItem));
//Outlook.MailItem mail = (Outlook.MailItem)Globals.ThisAddIn.Application.CreateItem(Outlook.OlItemType.olMailItem);
//Outlook.Recipient recipient = Globals.ThisAddIn.Application.Session.CreateRecipient("cindy@soundstewardship.com");
//email.Sender = recipient.AddressEntry;
//Outlook.Recipient recipient = app.Session.CreateRecipient("someone@example.com");
//email.Sender = recipient.AddressEntry;
//email.SentOnBehalfOfName = "someone@example.com";
email.Display(true); //was false
email.Subject = "You have a new appointment";
email.Importance = Outlook.OlImportance.olImportanceLow;
email.To = Application.Session.CurrentUser.AddressEntry.Address; //Current email address.
email.Body = "This email was automatically generated to remind you have an upcoming appointment on: " + x.Start.ToString();
email.Save();
email.Close(OlInspectorClose.olSave);
//((Outlook._MailItem)email).Send();
//email.Send();
//((Outlook._MailItem)mailItem).Send();
}
}
}
lastRun = DateTime.Now;
whileTrue = false;
}
else
{
/*
Outlook.MailItem email = new Outlook.MailItem();
email.Subject = "This is only a test.";
email.To = Application.Session.CurrentUser.AddressEntry.Address; //Current email address.
email.Body = "This is only a test.";
//email.Send();
((Outlook._MailItem)email).Send();
* */
}
}
}
catch (System.Exception e) //Microsoft.Office.Interop.Outlook.Exception e
{
MessageBox.Show(e.InnerException.ToString());
}
finally
{
app.Quit();
}
}
#endregion
}
}
您为什么要在 Outlook 主线程上休眠?然后遍历文件夹中的 all 项,而不是使用 Items.Restrict 或 Items.Find/FindNext?
首先,代码中不需要新建Outlook Application实例。您需要使用插件 class.
的应用程序 属性
At startup, I need it to read all appointments whose subject contains a certain string
不要使用 foreach 遍历文件夹中的所有项目。相反,您需要使用项目 class 的 Find/FindNext or Restrict 方法。您可以在以下文章中阅读有关这些方法的更多信息(包含示例代码):
How To: Retrieve Outlook calendar items using Find and FindNext methods
How To: Use Restrict method in Outlook to get calendar items
完成后,我建议使用收件人 class 的 Resolve or ResolveAll 方法根据地址簿解析所有收件人。
Also, like 75% of the time this addin loads directly as "inactive" and doesn't fire.
Microsoft Office 应用程序可以禁用行为异常的加载项。如果某个应用程序未加载您的加载项,则该应用程序可能已硬禁用或软禁用了您的加载项。
当加载项导致应用程序意外关闭时,可能会发生硬禁用。如果您在加载项中的启动事件处理程序正在执行时停止调试器,它也可能发生在您的开发计算机上。
当加载项产生不会导致应用程序意外关闭的错误时,可能会发生软禁用。例如,如果在启动事件处理程序 executing.When 时抛出未处理的异常,应用程序可能会软禁用加载项,您重新启用软禁用的加载项,应用程序会立即尝试加载加载项在。如果最初导致应用程序软禁用加载项的问题尚未解决,应用程序将再次软禁用加载项。在 How to: Re-enable an Add-in That Has Been Disabled 文章中阅读更多相关信息。
此外,Outlook 2013 还会监控加载项性能指标,例如加载项启动、关闭、文件夹切换、项目打开和调用频率。 Outlook 记录每个性能监控指标的经过时间(以毫秒为单位)。例如,启动指标测量 Outlook 启动期间每个连接的加载项所需的时间。然后,Outlook 会计算 5 次连续迭代的中值启动时间。如果中值启动时间超过 1000 毫秒(1 秒),则 Outlook 会禁用加载项并向用户显示加载项已被禁用的通知。用户可以选择始终启用加载项,在这种情况下,即使加载项超过 1000 毫秒性能阈值,Outlook 也不会禁用该加载项。有关详细信息,请参阅 Performance criteria for keeping add-ins enabled。
这基本上是对上一个问题的重新post,但我已经在同一问题上停留了 2 个多月,但没有取得任何进展。长话短说,有时它会触发,有时它不会。有时它加载一次,有时 Outlook 将其默认为 "inactive",我似乎无能为力。当它确实触发时,它会在尝试发送第一封电子邮件时挂断。因此,我在检查的日期范围之外有旧约会,并且会为这些约会显示消息框。当它到达 "new" 个约会(在日期范围内)时,有时它会弹出第一个消息框,但会在尝试发送电子邮件时挂断。有时,第一个 "good" 消息框无法弹出。我得到的关于这个问题的最后建议是建立一个日志文件,但我不知道 how/what 它对我有什么好处,或者老实说,我什至不确定我需要记录什么,当我询问时,提出它的那位先生从未回答过我。预先感谢您的帮助,这很容易成为我作为开发人员 运行 遇到过的最令人沮丧的事情之一。
using System;
using System.Threading;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using Outlook = Microsoft.Office.Interop.Outlook;
using Office = Microsoft.Office.Core;
using Microsoft.Office.Interop.Outlook;
using System.Windows.Forms;
namespace OutlookAddIn1
{
public partial class ThisAddIn
{
//Outlook.Inspectors inspectors;
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
doStuff();
}
private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
{
}
#region VSTO generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InternalStartup()
{
this.Startup += new System.EventHandler(ThisAddIn_Startup);
this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
}
//https://msdn.microsoft.com/en-us/library/ms268866.aspx
private void doStuff()
{
Outlook.Application app = new Outlook.Application();
Thread.Sleep(30000); //120 seconds - was 120000
DateTime firstRun = DateTime.Now; //So we can check every 24 hours? Maybe once initially as well.
DateTime lastRun = DateTime.Now;//.AddHours(1); //We're going to compare this to firstRun
bool whileTrue = true;
//int test = 0;
try
{
while (whileTrue)
{
if (whileTrue == true)//(firstRun > lastRun.AddDays(1))
{
Outlook.MAPIFolder calendarFolder = Application.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderCalendar);
Outlook.Items outlookCalendarItems = calendarFolder.Items;
outlookCalendarItems.IncludeRecurrences = true; //was true
List<Outlook.AppointmentItem> lst = new List<Outlook.AppointmentItem>();
foreach (Outlook.AppointmentItem item in outlookCalendarItems)
{
lst.Add(item);
//We can probably just handle logic in here without the second for loop that comes next
}
foreach (Outlook.AppointmentItem x in lst)
{
DateTime startDate = DateTime.Now.AddDays(1);
DateTime endDate = DateTime.Now.AddDays(5);
DateTime apptDate = x.Start;
if (x.Subject.ToLower().Contains("telos"))
{
MessageBox.Show("X: " + x.Start + "XYZ: " + x.Subject);
if (x.Start > startDate && x.Start < endDate)
{
Microsoft.Office.Interop.Outlook.MailItem email = app.CreateItem((OlItemType.olMailItem));
//Outlook.MailItem mail = (Outlook.MailItem)Globals.ThisAddIn.Application.CreateItem(Outlook.OlItemType.olMailItem);
//Outlook.Recipient recipient = Globals.ThisAddIn.Application.Session.CreateRecipient("cindy@soundstewardship.com");
//email.Sender = recipient.AddressEntry;
//Outlook.Recipient recipient = app.Session.CreateRecipient("someone@example.com");
//email.Sender = recipient.AddressEntry;
//email.SentOnBehalfOfName = "someone@example.com";
email.Display(true); //was false
email.Subject = "You have a new appointment";
email.Importance = Outlook.OlImportance.olImportanceLow;
email.To = Application.Session.CurrentUser.AddressEntry.Address; //Current email address.
email.Body = "This email was automatically generated to remind you have an upcoming appointment on: " + x.Start.ToString();
email.Save();
email.Close(OlInspectorClose.olSave);
//((Outlook._MailItem)email).Send();
//email.Send();
//((Outlook._MailItem)mailItem).Send();
}
}
}
lastRun = DateTime.Now;
whileTrue = false;
}
else
{
/*
Outlook.MailItem email = new Outlook.MailItem();
email.Subject = "This is only a test.";
email.To = Application.Session.CurrentUser.AddressEntry.Address; //Current email address.
email.Body = "This is only a test.";
//email.Send();
((Outlook._MailItem)email).Send();
* */
}
}
}
catch (System.Exception e) //Microsoft.Office.Interop.Outlook.Exception e
{
MessageBox.Show(e.InnerException.ToString());
}
finally
{
app.Quit();
}
}
#endregion
}
}
您为什么要在 Outlook 主线程上休眠?然后遍历文件夹中的 all 项,而不是使用 Items.Restrict 或 Items.Find/FindNext?
首先,代码中不需要新建Outlook Application实例。您需要使用插件 class.
的应用程序 属性At startup, I need it to read all appointments whose subject contains a certain string
不要使用 foreach 遍历文件夹中的所有项目。相反,您需要使用项目 class 的 Find/FindNext or Restrict 方法。您可以在以下文章中阅读有关这些方法的更多信息(包含示例代码):
How To: Retrieve Outlook calendar items using Find and FindNext methods
How To: Use Restrict method in Outlook to get calendar items
完成后,我建议使用收件人 class 的 Resolve or ResolveAll 方法根据地址簿解析所有收件人。
Also, like 75% of the time this addin loads directly as "inactive" and doesn't fire.
Microsoft Office 应用程序可以禁用行为异常的加载项。如果某个应用程序未加载您的加载项,则该应用程序可能已硬禁用或软禁用了您的加载项。
当加载项导致应用程序意外关闭时,可能会发生硬禁用。如果您在加载项中的启动事件处理程序正在执行时停止调试器,它也可能发生在您的开发计算机上。
当加载项产生不会导致应用程序意外关闭的错误时,可能会发生软禁用。例如,如果在启动事件处理程序 executing.When 时抛出未处理的异常,应用程序可能会软禁用加载项,您重新启用软禁用的加载项,应用程序会立即尝试加载加载项在。如果最初导致应用程序软禁用加载项的问题尚未解决,应用程序将再次软禁用加载项。在 How to: Re-enable an Add-in That Has Been Disabled 文章中阅读更多相关信息。
此外,Outlook 2013 还会监控加载项性能指标,例如加载项启动、关闭、文件夹切换、项目打开和调用频率。 Outlook 记录每个性能监控指标的经过时间(以毫秒为单位)。例如,启动指标测量 Outlook 启动期间每个连接的加载项所需的时间。然后,Outlook 会计算 5 次连续迭代的中值启动时间。如果中值启动时间超过 1000 毫秒(1 秒),则 Outlook 会禁用加载项并向用户显示加载项已被禁用的通知。用户可以选择始终启用加载项,在这种情况下,即使加载项超过 1000 毫秒性能阈值,Outlook 也不会禁用该加载项。有关详细信息,请参阅 Performance criteria for keeping add-ins enabled。