2017-05-03 3 views
0

Ich entwickle ein Outlook-Add-in, das mit einem Server über PHP kommuniziert.Outlook-Element ändern Ereignisse in C# fehlgeschlagen

Ich synchronisiere Daten zwischen Outlook-Elementen und Serverdaten.

Immer wenn der Benutzer eine Änderung an einem Element vornimmt (wie Drag'n'Drop im Kalender eines Termins zu einem anderen Datum oder einige Werte/Notizen ändern), wird das Elementwechselereignis ausgelöst und eine Synchronisation ausgelöst das passiert. Der Server sendet manchmal Daten zurück, die dann wiederum in das Outlook-Element geschrieben werden. In diesem Fall wird das Ereignis jedoch deaktiviert, sodass keine Kaskadierung stattfindet. Das ist alles gut, aber hier kommt die schlechte Sache:

Ich habe etwas wirklich merkwürdig bemerkt. Nachdem das Ereignis ausgelöst wurde und alles korrekt ist, entscheidet Outlook manchmal, das Ereignis noch einmal (oder sogar mehrmals) nach ein paar Sekunden (im Bereich von ~ 3 Sekunden bis ~ 22 Sekunden) auszulösen.

Das ist sehr unberechenbar und super nervig, da die Synchronisation auf den Items LastModificationTime beruht, die durch diese zufälligen Elementänderungen geändert werden.

Gibt es Möglichkeiten, diese Ereignisse zu deaktivieren oder sie zumindest von tatsächlichen Benutzeraktionen zu unterscheiden?

Ich habe auch die Ereignisse mit dem Add-In von Add-In-Express überwacht, und ich habe auch einige seltsame Aktivitäten dort.

Ich habe es auf mehreren PCs versucht, mit verschiedenen Versionen von Outlook/Windows installiert, und es passiert ziemlich viel überall.

Hier ist, wo ich die Ereignisse ein:

public static Outlook.ItemsEvents_ItemChangeEventHandler AppointmentChangeHandler; 
public static Outlook.ItemsEvents_ItemChangeEventHandler TaskChangeHandler; 

public static Outlook.Items appointments = null; 
public static Outlook.Items tasks = null; 
public void SetupEventHandlers() 
{ 
    Outlook.Application app = Globals.ThisAddIn.Application; 
    Outlook.NameSpace ns = app.GetNamespace("mapi"); 
    Outlook.MAPIFolder calendar = null; 
    Outlook.MAPIFolder tasksfolder = null; 
    try 
    { 
     calendar = OutlookHelper.GetMAPIFolderByName("Calendar Where I want my events to work"); 
     if (calendar != null) 
     { 
      appointments = calendar.Items; 
      AppointmentChangeHandler = new Outlook.ItemsEvents_ItemChangeEventHandler(Item_ItemChange); 
      appointments.ItemChange += AppointmentChangeHandler; 
     } 
    } 
    catch (Exception ex) 
    { 
     //failed to get calendar, and to add the itemchange event 
    } 

    try 
    { 
     tasksfolder = ns.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderTasks); 
     tasks = tasksfolder.Items; 
     TaskChangeHandler = new Outlook.ItemsEvents_ItemChangeEventHandler(Item_ItemChange); 
     tasks.ItemChange += TaskChangeHandler; 
    } 
    catch (Exception ex) 
    { 
     //failed to get tasks folder, and to add the itemchange event 
    } 
} 

Und hier ist der Event-Handler:

public static void Item_ItemChange(object Item) 
{ 
     if (Item.LastModificationTime() > Item.LastSync().AddSeconds(2) && !ProgrammaticChange) //I try to do something here: checking if the lastmodification time is more than 2 seconds after the last synchronization time, but as i said, it sometimes adds 22 seconds, sometimes 0... 
     { 
      ProgrammaticChange = true; //closing the door, so no cascading happens 

      SyncItem(Item); //this can change values on the outlook items, that could eventually trigger another event, but the boolean flag is true, so the event will not happen 

      ProgrammaticChange = false; //opening the door for new events 
     } 
} 
+0

Können Sie bitte den Code zeigen, den Sie schon seit einiger Zeit kennen. Danke –

+0

Hallo Jeremy! Danke für die Antwort, ich habe nur ein paar Code-Schnipsel hinzugefügt. – Laureant

Antwort

0

ItemChange mehrere Male sogar für eine scheinbar einzige Änderung abfeuern kann. Ein Beispiel wäre das Erstellen eines Elements in einer OST-Datei, die dann nach Exchange hochgeladen wird - der Server optimiert das Element und die Änderung wird dann auf die Clientseite heruntergeladen, die das Ereignis auslöst.

Verwenden Sie das ItemChange-Ereignis nicht als einzigen Synchronisierungspunkt - was passiert, wenn die Änderung vorgenommen wird, wenn Ihr Add-In nicht ausgeführt wird? Verwenden Sie es nur als Hinweis, dass die Synchronisierung früher als später ausgeführt werden muss.

Mehr als das, führen Sie nichts aus, was in einem Event-Handler lange dauern kann - wenn es zu lange dauert, wird das Event beim nächsten Mal möglicherweise nicht für ein anderes Objekt ausgelöst. Fügen Sie die Eintrags-ID des Elements (aber nicht das Element selbst!) Zu einer Liste hinzu, die Sie später entweder auf einem Zeitgeber oder in einem separaten Thread verarbeiten können.

Beachten Sie, dass OOM nicht für einen sekundären Thread verwendet werden kann (andernfalls wird eine Ausnahme ausgelöst). Sie können alle Daten des primären Threads abrufen, sodass bei der Synchronisierung der Schweregrad für einen sekundären Thread überschritten wird, ohne dass das Outlook-Objekt berührt wird. Wenn Sie auf Outlook-Daten in einem sekundären Thread zugreifen müssen, sind Extended MAPI (C++ oder Delphi) oder Redemption (es umschließt Extended MAPI und kann aus jeder beliebigen Sprache verwendet werden) Ihre einzigen Optionen. Im letzteren Fall (Redemption) können Sie den Wert der Namespace.MAPIOBJECT-Eigenschaft (es gibt IMAPISession-MAPI-Schnittstelle) im Hauptthread zwischenspeichern, dann in einem sekundären Thread eine Instanz des RDOSession-Objekts erstellen und die RDOSession.MAPIOBJECT-Eigenschaft festlegen auf den Wert, der im primären Thread gespeichert wurde. Sie können das Element dann mithilfe seiner Eingabe-ID mithilfe von RDOSession.GetMessageFromID öffnen.