【问题标题】:Outlook.MailItem.PropertyChange stops firing after 9 eventsOutlook.MailItem.PropertyChange 在 9 个事件后停止触发
【发布时间】:2020-12-31 20:42:43
【问题描述】:

我正在开发一个 Outlook 加载项,该加载项根据我的生产经理发送给我的电子邮件来管理项目列表。我的项目在 Outlook 中的 VBA 中运行良好,但我厌倦了看到使用 VBA 时弹出的安全消息。因此,我将其转换为 .Net 插件。我已经在 c# 中实现了这一点,但是我遇到了 Outlook.MailItem.PropertyChange 事件的事件侦听器的问题。这个想法是我可以使用快速单击类别将电子邮件移动到队列文件夹中,然后在移动后对该电子邮件运行一些处理。

我正在使用下面的代码订阅 Startup 方法中的事件处理程序...

    private void ThisAddIn_Startup(object sender, System.EventArgs e)
    {
        // Get the MAPI namespace
        _olNameSpace = this.Application.GetNamespace("MAPI");

        // Get the Application object
        _olApplication = this.Application;

        // Get the active Explorer object
        _olExplorer = _olApplication.ActiveExplorer();
        if (_olExplorer != null)
        {
            //Inbox Items and event listner(s)
            _olInBxItems = _olApplication.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox).Items;
            foreach (object Item in _olInBxItems)
            {
                if (Item is Outlook.MailItem)
                {
                    _olMailItem = (Outlook.MailItem)Item;
                    _olMailItem.PropertyChange -= new Outlook.ItemEvents_10_PropertyChangeEventHandler(Property_Change);
                    _olMailItem.PropertyChange += new Outlook.ItemEvents_10_PropertyChangeEventHandler(Property_Change);
                }
            }
        }
    }

我遇到的问题是该事件完美触发了大约 9 封电子邮件,然后它停止工作,但资源管理器中的第一封电子邮件除外。对于我的生活,我无法弄清楚其余电子邮件的事件触发器是什么。

我在类级别使用以下定义...

    internal static Outlook.NameSpace _olNameSpace { get; set; };
    internal static Outlook.Application _olApplication { get; set; }
    internal static Outlook.Items _olInBxItems { get; set; }
    internal static Outlook.MailItem _olMailItem { get; set; }
    internal static Outlook.Explorer _olExplorer { get; set; }

这是我的 PropertyChange 事件处理程序的定义...

    private static void Property_Change(string Name)
    {
        try
        {
            object curSelect = _olExplorer.Selection[1];
            if (((Outlook.MailItem)curSelect).Categories == "Post WIP")
            {
                MessageBox.Show(string.Format("{0} has changed in the {1} email.", Name, ((Outlook.MailItem)curSelect).Subject));
            }
            ((Outlook.MailItem)curSelect).Save();
        }
        catch(Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }

我错过了什么? 提前感谢您的关注。

【问题讨论】:

    标签: c# .net outlook-addin mailitem propertychangelistener


    【解决方案1】:

    设置事件处理程序时,添加前不需要删除:

    _olMailItem.PropertyChange -= new Outlook.ItemEvents_10_PropertyChangeEventHandler(Property_Change);
    _olMailItem.PropertyChange += new Outlook.ItemEvents_10_PropertyChangeEventHandler(Property_Change);
    

    您应该能够为每个邮件项目添加这样的内容:

    _olMailItem.PropertyChange += new Outlook.ItemEvents_10_PropertyChangeEventHandler(Property_Change);
    

    【讨论】:

    • 你会这么认为,特别是因为这是在启动时设置的。但是,这并不能解决我的问题,实际上会导致它仅适用于资源管理器中的第一封电子邮件。
    【解决方案2】:

    我相信我已经解决了我的问题。如果我没记错的话,这是一个超出范围的问题。我现在正在构建一个列表,其中包含资源管理器中订阅事件的电子邮件项目。我现在可以使用 Quick Click 类别超过 9 次,而触发器不会失败。这些是我为使其正常工作所做的更改 (***)...

    internal static Outlook.NameSpace _olNameSpace { get; set; };
    internal static Outlook.Application _olApplication { get; set; }
    internal static Outlook.Items _olInBxItems { get; set; }
    internal static Outlook.MailItem _olMailItem { get; set; }
    internal static Outlook.Explorer _olExplorer { get; set; }
    
    //*** Added this list to keep the emails in scope
    internal static List<Outlook.MailItem> _olMIList = new List<Outlook.MailItem>();
    
    private void ThisAddIn_Startup(object sender, System.EventArgs e)
    {
        // Get the MAPI namespace
        _olNameSpace = this.Application.GetNamespace("MAPI");
    
        // Get the Application object
        _olApplication = this.Application;
    
        // Get the active Explorer object
        _olExplorer = _olApplication.ActiveExplorer();
        if (_olExplorer != null)
        {
            //Inbox Items and event listner(s)
            _olInBxItems = _olApplication.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox).Items;
            foreach (object Item in _olInBxItems)
            {
                if (Item is Outlook.MailItem)
                {
                    //*** Changed this bit of code to use the list instead of the static _olMailItem
                    ((Outlook.MailItem)Item).PropertyChange -= new Outlook.ItemEvents_10_PropertyChangeEventHandler(Property_Change);
                    ((Outlook.MailItem)Item).PropertyChange += new Outlook.ItemEvents_10_PropertyChangeEventHandler(Property_Change);
                    _olMIList.Add((Outlook.MailItem)Item);
                }
            }
        }
    }
    

    我知道我不需要在订阅事件处理程序之前取消订阅它,但如果我这样做不会有任何伤害,并且如果处理程序已被订阅,它往往会更好地工作。

    欢迎任何 cmets,我还在学习 c# 和 .net 编程。

    【讨论】:

      【解决方案3】:

      为收件箱文件夹中的每个项目设置事件处理程序是一个可怕的想法。不要那样做。它会在最糟糕的时刻严重失败。如果文件夹中有几百个项目,在线模式肯定会失败。

      可以捕获Explorer.SelectionChange 事件并仅在所选项目(来自Explorer.Selection 集合)上设置事件处理程序,只要您立即使用Marshal.ReleaseComObject 释放对旧项目的引用。

      【讨论】:

      • 我尝试使用选择更改事件,但它似乎不断将订阅的多个副本添加到事件处理程序,即使在添加之前删除也是如此。你能举个例子说明什么时候发布什么内容吗?谢谢。
      • 我不确定这怎么可能 - 如果您在添加新项目之前先释放所有项目并清除列表,您怎么会得到相同消息的多个实例?
      • 不是同一条消息的多个实例,而是事件触发器的多个实例。
      • 我不确定你的意思。你真的需要展示你的代码。
      • 我在完成这项工作后将其丢弃。我将不得不尝试重新创建我遇到的问题。这是我假期后第一周重返工作岗位,所以我需要几天才能到达那里。当我有机会发布我的代码时,我会提到你。感谢@Dmitry Streblechenko 的帮助
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多