Outlook 2016 VSTO Folder Add event fires only once

强颜欢笑 提交于 2021-01-28 11:20:30

问题


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

回答1:


The following code is the problem:

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

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.



来源:https://stackoverflow.com/questions/42663830/outlook-2016-vsto-folder-add-event-fires-only-once

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!