Search code examples
c#outlookadd-in

ItemChangeEvent fired multiple times


I work on Outlook addin that is connected to an Owncloud (Caldav, Cardav). I use eventhandlers to detect when a user delete, create or update a contact item. In this case this will notify the server and do an update on his side.

storage.Aitems[storage.Aitems.Count - 1].ItemAdd += new Outlook.ItemsEvents_ItemAddEventHandler(contact_item_add);
storage.Aitems[storage.Aitems.Count - 1].ItemChange += new Outlook.ItemsEvents_ItemChangeEventHandler(contact_item_change);
((MAPIFolderEvents_12_Event)storage.Afolders[storage.Afolders.Count - 1]).BeforeItemMove += new MAPIFolderEvents_12_BeforeItemMoveEventHandler(contact_item_before_move);

When i find new contacts items from the server i add them right the addressbook folder. Outlook detect a new item or a update and then fire the eventshandlers. This is good in case there is only one call (I can say this from the server dont notify again the server or this is from the user notify the server) but i can't because the events are fired multiple times.

static void contact_item_change(object Item) {
        Microsoft.Office.Interop.Outlook.ContactItem contact = (Microsoft.Office.Interop.Outlook.ContactItem)Item;
        System.Diagnostics.Debug.WriteLine("[Modification contact]" + contact.FullName);
        // Need to know if item was created by code (server) or user
        Main.SyncContact(contact);
 }

Is it possible to know if an item is created trough the GUI or in my code ? I can't set a variable to know if it was created by user or by my code because of the multiple calls of events.

BTW i already succeed to fire add and delete only one time :

static void contact_item_add(object Item) {
        Microsoft.Office.Interop.Outlook.ContactItem contact = (Microsoft.Office.Interop.Outlook.ContactItem)Item;
        if (Contact.GetCreatedByUserProperty(contact, "USER")) {
            if (storage.PreviousAddedContactId != contact.EntryID)
            {
                System.Diagnostics.Debug.WriteLine("[Ajout contact]" + contact.FullName);
                Main.SyncContact(contact);
                storage.PreviousAddedContactId = contact.EntryID;
            }
        }
    }


static void contact_item_before_move(object item, MAPIFolder destinationFolder, ref bool cancel) {
        if ((destinationFolder == null) || (IsDeletedItemsFolder(destinationFolder))) {
            ContactItem contact = (item as ContactItem);
            if (storage.PreviousDeletedContactId != contact.EntryID)
            {
                System.Diagnostics.Debug.WriteLine("[Suppression du contact]" + contact.FullName);
                Main.DeleteContact(contact);
                storage.PreviousDeletedContactId = contact.EntryID;
            }
        }
    }

Thank you !


Solution

  • You can read MailItem.LastModificationTime immediately after calling MailItem.Save. When ItemChange event fires, you can compare the new modification time with what you cached and check if it is greater than some delta (1 second?).

    In case of Exchange store, you can also retrieve PR_CHANGE_KEY (DASL name http://schemas.microsoft.com/mapi/proptag/0x65E20102) property - it will change after each modification.