Outlook 2016 VSTO 文件夹添加事件仅触发一次 [英] Outlook 2016 VSTO Folder Add event fires only once

查看:75
本文介绍了Outlook 2016 VSTO 文件夹添加事件仅触发一次的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Am creating a outlook add-in to track mail processing from mailbox. Am wrapping the folders and the items(adding some events into it ) and storing them in a local list to avoid GC clearing all the events after first execution. However still the folder add event only fires once. Not sure what is the problem.

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 对象,以确保它保持被引用和活动状态.

The object that fires the events must be alive - in your case you set up an event handler on an implicit variable returned from the _wrappedFolder.Items property - as soon as the GC releases that implicit variable, no events will fire. Declare the Items object on the class level to make sure it stays referenced and alive.

这篇关于Outlook 2016 VSTO 文件夹添加事件仅触发一次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆