Outlook项目事件未正确触发

时间:2017-03-27 07:54:42

标签: c# outlook office-interop outlook-addin outlook-vba

我有一个Outlook加载项,每当更改任务/约会项目时我都需要进行一些计算。

我设法通过Inspector Wrapper获取了Item.Write和Item.BeforeDelete事件。这些工作非常好,但这还不够,因为Outlook中有更多事件可以改变(或做其他事情)对象。

Appointment MOVE事件中最重要的事件之一,我在日历中拖放日历项目,并更改其日期。 经过进一步检查后,我发现,BeforeItemMoveEventHandler对此并不是很好,所以我只是简单地使用Item集合对象上的ItemChange事件。 为了实现这一点,我有一个在启动时运行的函数,看起来像这样:

public Outlook.ItemsEvents_ItemChangeEventHandler ChangeHandler;
public Outlook.MAPIFolderEvents_12_BeforeItemMoveEventHandler MoveHandler;
public void SetupEventHandlers()
{
    Outlook.Application app = Globals.ThisAddIn.Application;
    Outlook.NameSpace ns = app.GetNamespace("mapi");
    Outlook.MAPIFolder calendar = null;
    Outlook.Folder calendarFolder = null;
    Outlook.Items appointments = null;
    try
    {
        calendar = OutlookHelper.GetMAPIFolderByName("My Calendar");
        appointments = calendar.Items;
        ChangeHandler = new Outlook.ItemsEvents_ItemChangeEventHandler(Appointments_ItemChange);
        appointments.ItemChange += ChangeHandler;

        calendarFolder = OutlookHelper.GetOutlookFolderByName("My Calendar");
        MoveHandler = new Outlook.MAPIFolderEvents_12_BeforeItemMoveEventHandler(Appointments_ItemMove);
        calendarFolder.BeforeItemMove += MoveHandler;
    }
    catch (Exception ex)
    {
        //failed to get calendar, and to add the itemchange event;
    }
}

我在许多地方都读过,必须将事件指定为全局变量,以便不进行垃圾回收。

尝试了两种方式,但结果是,事件被触发2-5次然后它就会停止,没有任何错误消息。

那里的2个子功能(GetMAPIFolderByName和GetOutlookFolderByName)100%返回请求的对象和类型。如果它们是问题的根源,那么根本不起作用。

问题#1 启动应用程序时会触发Appointments_ItemChange事件。因为我希望服务器同步类型的事情与这些事件相关联,所以在启动时使用不必要的数据对服务器进行调用并不是很好。应该有一种方法可以在启动时忽略这个ItemChange事件......?

问题#2 这些事件是随机发射的!我安装了一个Outlook事件监视器加载项,它显示了触发了什么类型的事件以及何时调用它们,有时它甚至会在1分钟后触发ItemChange事件。此外,它会触发多个(为了解决这个问题,我有一个解决方案,你可以在下面的代码示例中看到)

Appointments_ItemChange函数看起来像这个

public Boolean AppointmentThreadRunning = false;
public Thread AppointmentItemChangeThread;
public void Appointments_ItemChange(object Item)
{
    if (!AppointmentThreadRunning) //check if there is a running thread
    {
        AppointmentItemChangeThread = new Thread(delegate ()
        {
            AppointmentItemChangeThreadedFunction(Item); //call the thread which will change the value of the boolean and keep it for 3 seconds
        });
        AppointmentItemChangeThread.Start();
        Outlook.AppointmentItem appt = (Outlook.AppointmentItem)Item;
        CallSyncAppointmentChange(appt); //call the sync server function
    }
}

public void AppointmentItemChangeThreadedFunction(dynamic OutlookItem)
{
    AppointmentThreadRunning = true;
    //wait 3 seconds, so if Outlook decides to fire another ItemChange it will not call the SYNC 
    Thread.Sleep(3000); 
    AppointmentThreadRunning = false;
}

1 个答案:

答案 0 :(得分:0)

仅使事件处理程序成为类变量是不够的。我不得不将约会(Outlook.Items类型)作为一个全局变量......