FreeG
FreeG

Reputation: 95

outlook hangs up after hooking up folder.Items.ItemAdd Events of every folder

I have following Situation: Iam programming an Outlook 2010 AddIn and want a global event that notifies me when any item is added to any folder. The object model of outlook doesn't offer a global ItemAdd event it only offers the ItemAdd Event of the Items Collection of a folder. So to solve the problem i've bundled all ItemAddEvents to a GlobalItemAddedEvent of the FolderManager class.

The Following Problem: Everything works fine on my machine but when the customer executes it, it takes about 2 minutes to initialize (many different postboxes and folders) but thats ok it is probably initialized correctly. When finished loading and Outlook appears, Outlook hangs up and doesn't take any commands and has to be killed by the task manager

iam really struggling on this and can't find any solution or explanation. Does anybody has a clue whats going on here and how to solve it? thanks!

Example Code:

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

Upvotes: 0

Views: 641

Answers (2)

Dmitry Streblechenko
Dmitry Streblechenko

Reputation: 66296

MAPI events exposed by Items.ItemAdd/etc. were designed for the UI purposes only. You should not use them for any kind of synchronization. Events are not guaranteed to fire.

That being said, on the MAPI level, the store (IMsgStore) will fire the fnevObjectCreated event when a message is created. You can use that event in Extended MAPI only (C++ or Delphi). If using Redemption is an option (I am its author), it exposes the RDOStore.OnMessageCreated event.

Upvotes: 1

Eugene Astafiev
Eugene Astafiev

Reputation: 49455

I'd recommend subscribing to the Extended MAPI notifications (low-level events) instead of using the Outlook object model. Keeping a bunch of COM objects alive is not a good idea with Outlook. I always recommend releasing underlying COM objects instantly. Use System.Runtime.InteropServices.Marshal.ReleaseComObject to release an Outlook object when you have finished using it. This is particularly important if your add-in attempts to enumerate more than 256 Outlook items in a collection that is stored on a Microsoft Exchange Server. If you do not release these objects in a timely manner, you can reach the limit imposed by Exchange on the maximum number of items opened at any one time. Then set a variable to Nothing in Visual Basic (null in C#) to release the reference to the object. Read more about that in the Systematically Releasing Objects article.

For example, as a workaround you may consider using any wrapper around Extended MAPI (such as Redemption).

Upvotes: 2

Related Questions