坚持了 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