挂钩文件夹后,outlook挂起.Items.ItemAdd每个文件夹的事件

时间:2016-01-13 11:05:43

标签: c# events outlook add-in

我有以下情况: Iam编程Outlook 2010 AddIn并想要一个全局事件,当任何项目添加到任何文件夹时通知我。 outlook的对象模型不提供全局ItemAdd事件,它仅提供文件夹的Items Collection的ItemAdd事件。 因此,为了解决这个问题,我将所有ItemAddEvents捆绑到了FolderManager类的GlobalItemAddedEvent。

以下问题: 一切都在我的机器上工作正常但是当客户执行它时,初始化大约需要2分钟(许多不同的邮箱和文件夹),但没关系,它可能正确初始化。完成加载并显示Outlook后,Outlook挂起并且不接受任何命令,并且必须被任务管理器杀死

我真的在这方面苦苦挣扎,无法找到任何解决方案或解释。有没有人知道在这里发生什么以及如何解决它?谢谢!

示例代码:

public class FolderManager : IFolderManager
{
    public event GlobalItemAdd GlobalItemAdded;
    private Dictionary<string, FolderContainer> _foldersMap = new Dictionary<string, FolderContainer>();

    private void InitFolders()
    {
        HashSet<string> excludeFolderIds = new HashSet<string>();
        Outlook.Stores stores = application.Session.Stores;
        foreach(Outlook.Store store in stores){
            //exclude outbox folder from event
            try
            {
                Outlook.MAPIFolder exclude = store.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderOutbox);
                excludeFolderIds.Add(exclude.EntryID);
            }
            catch(COMException ex){

            }
        }
        //attach events to folders
        List<Outlook.Folder> allFolders = application.Session.GetAllFolders();
        foreach (Outlook.Folder folder in allFolders)
        {

            if(excludeFolderIds.Contains(folder.EntryID)){
                continue;
            }
            FolderContainer folderContainer = new FolderContainer(folder, this);
            _foldersMap[folderContainer.EntryID] = folderContainer;
        }
    }  
    public void ItemAdded(object added, Outlook.MAPIFolder parent)
    {
        OnGlobalItemAdded(added,parent);
    }  
}  

public class FolderContainer{
//Instance variables & Properties
//...
//...

    public FolderContainer(Outlook.MAPIFolder folder,IFolderManager manager)
    {
        _manager = manager;

        _thisFolder = folder;
        _OlItems = folder.Items;
        _OlFolders = folder.Folders;

        if (_OlItems != null)
        {
            _OlItems.ItemAdd += new Outlook.ItemsEvents_ItemAddEventHandler(ItemAdd);
        }
        if (_OlFolders != null)
        {
            _OlFolders.FolderAdd += new Outlook.FoldersEvents_FolderAddEventHandler(FolderAdd);
        }
    }

    private void ItemAdd(object item)
    {
        _manager.ItemAdded(item,_thisFolder);
    }
}

2 个答案:

答案 0 :(得分:2)

我建议订阅扩展MAPI通知(低级别事件)而不是使用Outlook对象模型。使用Outlook保持一堆COM对象不是一个好主意。我总是建议立即释放底层的COM对象。完成使用后,使用System.Runtime.InteropServices.Marshal.ReleaseComObject释放Outlook对象。如果您的加载项尝试枚举存储在Microsoft Exchange Server上的集合中超过256个Outlook项目,这一点尤为重要。如果您未及时发布这些对象,则可以达到Exchange对任何时候打开的最大项目数的限制。然后在Visual Basic中将变量设置为Nothing(C#中为null)以释放对该对象的引用。请在Systematically Releasing Objects文章中详细了解相关内容。

例如,作为一种解决方法,您可以考虑使用扩展MAPI周围的任何包装(例如Redemption)。

答案 1 :(得分:1)

Items.ItemAdd / etc公开的MAPI事件。仅用于UI目的。您不应该将它们用于任何类型的同步。事件不能保证解雇。

话虽如此,在MAPI级别上,商店(IMsgStore)将在创建消息时触发fnevObjectCreated事件。您只能在扩展MAPI(C ++或Delphi)中使用该事件。如果使用Redemption是一个选项,则会公开RDOSession.OnMessageCreated事件。