Interop Outlook 2007 在垃圾收集后丢失 ItemSend 事件

Interop Outlook 2007 losing ItemSend event after Garbage Collection

我正在尝试挂钩 ItemSend 事件(一旦用户在 Outlook 中单击 "Send",该事件就会触发),但我遇到的问题是 GC 在用户单击 [=15= 之前是否触发] 事件挂钩丢失。我已经通过强制 gc.Collect 测试了这个。我正在使用带有最新服务包的 outlook 2007。起初我认为问题是由于范围引起的,但我已经剥离了所有内容,但仍然无法确定为什么我的事件挂钩被删除。任何人都可以阐明这一点吗?非常感谢。

项目参考: Microsoft.Office.Interop.Outlook

using System.Windows.Forms;
using Microsoft.Office.Interop.Outlook;

namespace WindowsFormsApplication20
{
    public partial class Form1 : Form
    {
        private Microsoft.Office.Interop.Outlook.Application outlook;
        private MailItem mailItem;

        public Form1()
        {
            InitializeComponent();

            outlook = new Microsoft.Office.Interop.Outlook.Application();
            outlook.Application.ItemSend += ThisApplication_SentMail;

            mailItem = (MailItem)outlook.CreateItem(OlItemType.olMailItem);
            mailItem.Recipients.Add("asd@hotmail.com");
            mailItem.Body = "test123";
            mailItem.Display();

            // when gc collect, ItemSend event no longer fires (force gc.collect to test)
            System.GC.Collect();
        }

        private void ThisApplication_SentMail(object item, ref bool cancel)
        {
            int halt = 0; //breakpoint here
        }
    }
}

这在技术上是正确的,因为它是处置问题。看来,当 window 从您的应用程序分离时,事件将断开连接。 如果将 Display 设置为 True,您应该会发现这不会发生。模态标志的目的就是专门为此。如果您需要锁定当前线程直到用户完成,请使用 true,否则使用 false(或什么都不做)。

Modal Optional Variant
True to make the window modal. The default value is False.

例如

        outlook = new Microsoft.Office.Interop.Outlook.Application();
        outlook.Application.ItemSend += ThisApplication_SentMail;

        mailItem = (MailItem)outlook.CreateItem(OlItemType.olMailItem);
        mailItem.Recipients.Add("asd@hotmail.com");
        mailItem.Body = "test123";
        mailItem.Display(true);

Microsoft's Documentation on Display

您使用的是多点表示法,这意味着编译器会创建一个隐式变量来保存该值,一旦该变量超出范围,它就有资格进行垃圾回收,并且当 GC 运行一些几秒钟后,将不再引发事件。

换行

outlook.Application.ItemSend += ThisApplication_SentMail;

outlook.ItemSend += ThisApplication_SentMail;