Outlook 2016 VSTO 文件夹添加事件仅触发一次

2023-12-30

正在创建一个 Outlook 插件来跟踪邮箱中的邮件处理。我正在包装文件夹和项目(向其中添加一些事件)并将它们存储在本地列表中,以避免 GC 在首次执行后清除所有事件。但是,文件夹添加事件仍然只触发一次。不确定是什么问题。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using OutlookNS = Microsoft.Office.Interop.Outlook;
using Office = Microsoft.Office.Core;
using System.Net;
using System.Windows.Forms;


namespace OutlookAuditor
{
    public partial class ThisAddIn
    {
        #region private variables

        OutlookNS._NameSpace outNS;
        OutlookNS.Explorer explorer;
        string profileName = string.Empty;
        List<SuperMailFolder> wrappedFolders = new List<SuperMailFolder>();
        Logger logger = new Logger();
        SuperMailFolder folderToWrap;
        #endregion

        private void ThisAddIn_Startup(object sender, System.EventArgs e)
        {
            try
            {
                OutlookNS.Application application = this.Application;

                //Get the MAPI namespace
                outNS = application.GetNamespace("MAPI");
                //Get UserName
                string profileName = outNS.CurrentUser.Name;

                //Create a new outlook application
                //I had to do this because my systems default mail box was ost file other just the below commented line is enough
                //OutlookNS.MAPIFolder inbox = outNS.GetDefaultFolder(OutlookNS.OlDefaultFolders.olFolderInbox) as OutlookNS.MAPIFolder;
                OutlookNS.MAPIFolder inbox;
                OutlookNS.Folders folders = outNS.Folders;
                OutlookNS.MAPIFolder selectedFolder = null;
                if (folders.Count > 1)
                {

                    List<string> folderNames = new List<string>();
                    foreach (OutlookNS.Folder folder in folders)
                    {
                        folderNames.Add(folder.Name);
                    }
                    using (selectMailBox frmSelect = new selectMailBox(folderNames))
                    {

                        if (DialogResult.OK == frmSelect.ShowDialog())
                        {
                            selectedFolder = folders[frmSelect.SelectedFolder];
                        }
                    }


                }
                else
                {
                    selectedFolder = folders[1];
                }
                logger.SaveLog("Folder Selected " + selectedFolder.Name);
                inbox = selectedFolder.Folders["Inbox"];//as OutlookNS.MAPIFolder;
                //Create a super mail folder
                folderToWrap = new SuperMailFolder(inbox, profileName);
                wrappedFolders.Add(folderToWrap);
                wrappedFolders.AddRange(folderToWrap.wrappedSubFolders);

                //System.Runtime.InteropServices.Marshal.ReleaseComObject(inbox);
            }
            catch (Exception ex)
            {
                logger.WriteException(ex);
            }
            finally
            {

            }
        }

        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);
        }

        #endregion
    }

    #region SuperMailItem object
    class SuperMailItem
    {
        //local variable for avoiding GC invocation
        OutlookNS.MailItem item;
        string _profileName;
        OutlookAuditor.Common.AuditItem auditItem;
        string parentMailID;
        string _folderName = string.Empty;
        OutlookNS.MailItem replyItem;
        Logger logger = new Logger();
        //constructor that wraps mail item with required events
        internal SuperMailItem(OutlookNS.MailItem MailItemToWrap, string profileName,string folderName)
        {
            try
            {
                item = MailItemToWrap as OutlookNS.MailItem;

                _folderName = folderName;
                if (item is OutlookNS.MailItem)
                {
                    logger.SaveLog(item.Subject);
                    item.PropertyChange += MailItemToWrap_PropertyChange;
                    //item.PropertyChange += new OutlookNS.ItemEvents_10_PropertyChangeEventHandler(MailItemToWrap_PropertyChange);

                    ((OutlookNS.ItemEvents_10_Event)item).Reply += SuperMailItem_Reply;
                }
            }
            catch(Exception ex)
            {
                logger.WriteException(ex,"SuperMailItem Constructor");
            }

        }

        void SuperMailItem_Reply(object Response, ref bool Cancel)
        {
            try
            {
                parentMailID = string.Empty;
                replyItem = Response as OutlookNS.MailItem;
                ((OutlookNS.ItemEvents_10_Event)replyItem).Send += SuperMailItem_Send;
            }
            catch(Exception ex)
            {
                logger.WriteException(ex);
            }

        }


        //this event is not firing
        void SuperMailItem_Send(ref bool Cancel)
        {
            try
            {
                if (!Cancel)
                {
                    createAuditItem();
                    auditItem.ActionDescription = "REPLY_SENT";
                    SaveLog();
                }
            }
            catch(Exception ex)
            {
                logger.WriteException(ex);
            }

        }

        //property change event- fires when any property of a mail item changes
        void MailItemToWrap_PropertyChange(string Name)
        {
            try
            {

                createAuditItem();
                //We are interested in UnRead property, if this property changes audit.
                if (Name == "UnRead")
                {
                    if (!item.UnRead)
                    {
                        auditItem.ActionDescription = "MAIL_READ";
                    }
                    else
                    {
                        auditItem.ActionDescription = "MAIL_UNREAD";
                    }
                }
                SaveLog();
            }
            catch(Exception ex)
            {
                logger.WriteException(ex);
            }
        }

        void createAuditItem()
        {
            auditItem = new Common.AuditItem();
            auditItem.ActionTimestamp = DateTime.Now;
            auditItem.EntryID = item.EntryID;
            auditItem.ProfileName = _profileName;
            auditItem.ReceivedTimestamp = item.ReceivedTime;
            auditItem.SystemIP = Helper.SystemIP();
            auditItem.UserName = Helper.UserID();
            auditItem.OriginalMailSentBy = item.Sender.Name;
            auditItem.FolderName = _folderName;
            auditItem.Subject = item.Subject;
        }

        void SaveLog()
        {
            Logger logger = new Logger();
            logger.Save(auditItem);
        }
    }

    #endregion

    #region SuperMailFolder object
    class SuperMailFolder
    {
        #region private variables
        OutlookNS.MAPIFolder _wrappedFolder;
        string _profileName;
        List<SuperMailItem> wrappedItems = new List<SuperMailItem>();
        public List<SuperMailFolder> wrappedSubFolders = new List<SuperMailFolder>();
        string folderName = string.Empty;
        Logger logger = new Logger();
        #endregion

        #region constructor
        internal SuperMailFolder(OutlookNS.MAPIFolder folder, string profileName)
        {
            try
            {
                //assign it to local private master
                _wrappedFolder = folder;
                folderName = folder.Name;
                _profileName = profileName;
                //assign event handlers for the folder
                _wrappedFolder.Items.ItemAdd +=Items_ItemAdd;
                _wrappedFolder.Items.ItemRemove += Items_ItemRemove;

                refreshItemList();

                //Go through all the subfolders and wrap them as well
                foreach (OutlookNS.MAPIFolder tmpFolder in _wrappedFolder.Folders)
                {
                    logger.SaveLog("Wrapping folder " + tmpFolder.Name);
                    SuperMailFolder tmpWrapFolder = new SuperMailFolder(tmpFolder, _profileName);
                    wrappedSubFolders.Add(tmpWrapFolder);
                    wrappedSubFolders.AddRange(tmpWrapFolder.wrappedSubFolders);
                }

            }
            catch(Exception ex)
            {
                logger.WriteException(ex);
            }
        }
        #endregion

        void Items_ItemRemove()
        {
            refreshItemList();
        }

        #region Handler of addition item into a folder
        void Items_ItemAdd(object Item)
        {
            try
            {
                if (Item is OutlookNS.MailItem)
                {

                    OutlookNS.MailItem item = Item as OutlookNS.MailItem;

                    wrappedItems.Add(new SuperMailItem(item, _profileName, folderName));
                    logger.SaveLog("Adding new item. New collection count:" + wrappedItems.Count.ToString());
                    OutlookAuditor.Common.AuditItem auditItem = new Common.AuditItem();
                    auditItem.ActionTimestamp = DateTime.Now;
                    auditItem.EntryID = item.EntryID;
                    auditItem.ProfileName = _profileName;
                    auditItem.ReceivedTimestamp = item.ReceivedTime;
                    auditItem.SystemIP = Helper.SystemIP();
                    auditItem.UserName = Helper.UserID();
                    auditItem.ActionDescription = "FOLDER_ADD";
                    auditItem.FolderName = folderName;
                    auditItem.OriginalMailSentBy = item.Sender.Name;
                    auditItem.Subject = item.Subject;
                    logger.Save(auditItem);
                }
            }
            catch(Exception ex)
            {
                logger.WriteException(ex);
            }
        }

        void refreshItemList()
        {

            try
            {
                wrappedItems.Clear();
                wrappedItems = new List<SuperMailItem>();
                logger.SaveLog("Wrapping items in " + folderName);
                //Go through all the items and wrap it.
                foreach (OutlookNS.MailItem item in _wrappedFolder.Items)
                {
                    try
                    {
                        if (item is OutlookNS.MailItem)
                        {
                            OutlookNS.MailItem mailItem = item as OutlookNS.MailItem;
                            SuperMailItem wrappedItem = new SuperMailItem(mailItem, _profileName, folderName);
                            wrappedItems.Add(wrappedItem);
                        }
                    }
                    catch (Exception ex)
                    {
                        logger.WriteException(ex);
                    }
                }
                logger.SaveLog("Wrapped items in " + folderName + ":" + wrappedItems.Count.ToString());
            }
            catch(Exception ex)
            {
                logger.WriteException(ex);
            }
        }
        #endregion
    }
    #endregion

    static class Helper
    {
        public static string SystemIP()
        {
            string hostName = Dns.GetHostName();
            string hostAddress = Dns.GetHostByName(hostName).AddressList[0].ToString();
            return hostAddress;
        }

        public static string UserID()
        {
            return System.Security.Principal.WindowsIdentity.GetCurrent().Name;
        }
    }
}

下面的代码就是问题所在:

        _wrappedFolder.Items.ItemAdd +=Items_ItemAdd;
        _wrappedFolder.Items.ItemRemove += Items_ItemRemove;

触发事件的对象必须处于活动状态 - 在您的情况下,您在从 _wrappedFolder.Items 属性返回的隐式变量上设置事件处理程序 - 一旦 GC 释放该隐式变量,就不会触发任何事件。在类级别声明 Items 对象,以确保它保持被引用和活动状态。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Outlook 2016 VSTO 文件夹添加事件仅触发一次 的相关文章

随机推荐

  • Spring ApplicationContext.getBean(Class c) 不适用于代理类

    我需要通过豆类的类类型查找豆类 当bean被代理包装时 某些方法是 Transactional ApplicatoinContext无法找到它们 我发现如果我通过接口查找它们 它是有效的 但在这种情况下我正在使用具体的类类型 我知道该 be
  • AJAX - Spring 控制器 - JSP

    我想生成对 Spring MVC 控制器的 AJAX 基于 jQuery 请求 并将带有对象的 Collection 返回到 jsp 我有两个烦恼 1 AJAX成功块不起作用 数据类型的东西 2 不知道如何将这个对象显示到jsp上
  • C 中的 Salted sha512,无法与 Symfony2 的 FOSUserBundle 同步

    我的开发分为两个部分 该网站是一个使用 FOSUserBundle 的 Symfony 应用程序 它使用 SHA512 和盐对密码进行加密 一个用 C 语言编程的身份验证模块 一旦给出盐和明文密码 它应该能够重现 SHA512 加盐哈希 有
  • 如何用数据库数据填充TableView

    我一直在尝试加载TableView从数据库查询数据 但似乎无法让它工作 这是我第一次尝试填充TableView与数据库查询项目 以防我的代码看起来杂乱且远非良好 FXML 是通过 JavaFX SceneBuilder 完成的 这是数据库查
  • protobuf-net AddField 忽略 IgnoreListHandling

    我有这个数据结构声明 ProtoContract public class NotACollectionHolder public NotACollection some objects ProtoContract IgnoreListHa
  • ctypes.pointer、ctypes.POINTER 和 ctypes.byref 之间有什么区别?

    在ctypes中 指针和byref有什么区别 它们似乎都是将指针传递给函数的一种方式 例如作为输出参数 从功能上来说 它们是等效的 但是 那蟒蛇文档 http docs python org release 2 5 2 lib ctypes
  • 为什么我的 WinForm 控件在绘制事件之前闪烁?

    我有一个表单 其中加载了一个用户控件 其中包含 3 个其他用户控件 每次我移动到另一个选项卡并返回到该用户控件时 其中的 3 个控件甚至在事件触发之前就会闪烁 我尝试了一切 包括 this DoubleBuffered true this
  • 水平平滑动量滚动

    问题 我需要平滑一些鼠标滚轮水平的滚动到此布局 https jsfiddle net 38qLnzkh https jsfiddle net 38qLnzkh 选择 我发现这个脚本完全符合我的要求 但它似乎只能垂直工作 黄油 js http
  • VS2017 设置项目 - 在哪里?

    我正在尝试为 C 项目创建安装项目 安装程序 但在 VS2017 中找不到 安装项目 模板 在 VS2015 中它位于 其他项目类型 gt gt 设置和部署 gt gt Visual Studio 安装程序 我用过几次没有任何问题 我的 V
  • 带有半圆边缘的 android 按钮

    我正在尝试创建一个用于 Android 项目中的图像按钮的形状 该形状基本上在左侧和右侧都有半圆 我想我可以只使用带有半径的形状 XML 但这只是圆角 我需要整个左侧和右侧是半圆 如下图所示 我当前的形状 XML 如下所示
  • Java Apache FileUtils readFileToString 和 writeStringToFile 问题

    我需要将 java 文件 实际上是 pdf 解析为字符串并返回到文件 在这些过程之间 我将对给定的字符串应用一些补丁 但这在本例中并不重要 我开发了以下 JUnit 测试用例 String f1String FileUtils readFi
  • .Net - 什么时候 List.ForEach 优于标准 foreach 循环?

    通用列表类有一个 ForEach Action
  • `null` 被视为字符串?

    String s null s s hai System out println s Output nullhai 我以为这会让我陷入 NPE 状态 背后的根本逻辑是什么 使用时不抛出NPE 级联 使用时抛出NPE For s s hai
  • 为什么 Jackson 要使用以类命名的额外层来包裹我的对象?

    当我序列化时 public class FOO int field1 String field2 我得到以下内容 FOO field1 0 field2 value 你能指出我怎样才能使输出看起来像这样 field1 0 field2 va
  • 什么会使单个任务执行器停止处理任务?

    我正在使用一个java util concurrent ExecutorService我通过调用获得的Executors newSingleThreadExecutor This ExecutorService有时会停止处理任务 即使它尚未
  • 如何将 Owl Carousel 中的图像居中

    我的猫头鹰旋转木马包含不同宽度和高度的图片 如何将它们水平和垂直居中对齐 owl example owlCarousel navigation true div class owl carousel div img div div
  • 按名称对 'ls' 输出进行排序

    你能排序一个ls https en wikipedia org wiki Ls按名称列出 我的 ls 默认按名称排序 你看到什么了 man ls states 列出有关文件的信息 默认为当前目录 如果没有 则按字母顺序对条目进行排序 cft
  • 如果值为 0,如何隐藏 HTML 表格行

    我有一个 HTML 表格 有 4 列 Item Code Item Name Category Name and Quantity其中数量为输入字段 我正在做的是用 JSON 数据填充表 最初输入字段设置为 0 当用户由于大量数据而在输入字
  • 当类型嵌套时,TYPE_USE 注释会丢失,通用接口[重复]

    这个问题在这里已经有答案了 当带注释的类型是嵌套的泛型接口时 似乎无法通过反射访问 TYPE USE 注释 请观察以下示例 import java lang annotation ElementType import java lang a
  • Outlook 2016 VSTO 文件夹添加事件仅触发一次

    正在创建一个 Outlook 插件来跟踪邮箱中的邮件处理 我正在包装文件夹和项目 向其中添加一些事件 并将它们存储在本地列表中 以避免 GC 在首次执行后清除所有事件 但是 文件夹添加事件仍然只触发一次 不确定是什么问题 using Sys