2017-03-08 138 views
1

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

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

回答

3

下面的代码的问题是:

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

触发该事件必须是活的对象 - 在你的情况设置一个事件处理程序从_wrappedFolder.Items返回一个隐含变量属性 - 只要GC释放隐式变量,就不会触发事件。在类级别上声明Items对象,以确保它保持引用并保持活动状态。

+0

谢谢队友。那诀窍 – Ramki

+0

也帮助了我。 GC问题很棘手。 – Roland