简体   繁体   中英

Outlook 2016 VSTO Folder Add event fires only once

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

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM