2017-05-03 3 views
0

PHP를 통해 서버와 통신하는 Outlook 추가 기능을 개발하고 있습니다.C#의 Outlook 항목 변경 이벤트가 잘못되었습니다.

Outlook 항목과 서버 데이터간에 데이터를 동기화하고 있습니다.

사용자가 약속을 다른 날짜로 드래그 앤 드롭하거나 일부 값/메모 등을 변경할 때마다 항목 변경 이벤트가 발생하고 동기화됩니다. 일어난다. 서버는 때때로 일부 데이터를 다시 보내서 다시 Outlook 항목에 기록하지만이 경우 이벤트가 비활성화되므로 계단식 연결이 없습니다. 이것은 모두 좋지만, 여기 나쁜 것이 있습니다 :

나는 정말 이상한 것을 발견했습니다. 이벤트가 발생하고 모든 것이 올 바른 경우 Outlook에서 몇 초 (~ 3 초 ~ 22 초) 후 이벤트를 다시 한 번 (또는 여러 번) 다시 실행하기로 결정할 때가 있습니다.

동기화는 임의 항목 변경으로 인해 변경되는 항목 LastModificationTime에 의존하기 때문에 예측할 수없고 매우 귀찮습니다.

이러한 이벤트를 사용 중지하는 방법이나 실제 사용자 동작과 구분할 수있는 방법은 무엇입니까?

또한 Add-In-Express에서 작성한 addin을 사용하여 이벤트를 모니터했으며 거기에서도 이상한 활동이있었습니다.

다른 버전의 Outlook/Windows가 설치된 여러 대의 PC에서 시험해 보았습니다. 거의 모든 곳에서 발생합니다. 여기

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

그리고 이벤트 핸들러의 :

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

코드를 보여 주시겠습니까? 잠시 둘러 보셨습니까? 감사합니다 –

+0

안녕 Jeremy! 답장을 보내 주셔서 감사합니다. 방금 일부 코드 조각을 추가했습니다. – Laureant

답변

0

ItemChange도 겉으로는 하나의 변화를 여러 번 해고 할 수 내가 이벤트를 설정할 경우

는 여기에 있습니다. 예를 들어 OST 파일에 항목을 만들어 Exchange에 업로드하면 서버가 항목을 조정 한 다음 변경 내용을 클라이언트 측에 다운로드하여 이벤트를 발생시킵니다.

ItemChange 이벤트를 유일한 동기화 진입 점으로 사용하지 마십시오. 추가 기능이 실행되지 않을 때 변경하면 어떻게됩니까? 동기화를 나중에 실행하는 것이 아니라 더 빨리 실행해야한다는 힌트로만 사용하십시오.

이상, 이벤트 처리기에서 시간이 오래 걸릴 수있는 항목을 실행하지 마십시오. 실행하는 데 시간이 너무 오래 걸리면 다른 항목에 대해 다음 번에 이벤트가 실행되지 않을 수 있습니다. 타이머 또는 별도의 스레드에서 나중에 처리 할 수있는 항목의 항목 ID (항목 자체는 아님)를 목록에 추가하십시오.

OOM은 보조 스레드에서 사용할 수 없습니다 (그렇지 않으면 예외가 발생 함). 기본 스레드의 모든 데이터를 검색하여 Outlook 개체를 건드리지 않고 보조 스레드에서 모든 동기화 작업을 수행 할 수 있습니다. 보조 스레드 인 Outlook 데이터에 액세스해야하는 경우 확장 MAPI (C++ 또는 Delphi) 또는 Redemption (확장 MAPI를 래핑하고 모든 언어에서 사용할 수 있음) 만 옵션입니다. 후자의 경우 (Redemption)에서는 주 스레드에서 Namespace.MAPIOBJECT 속성 값 (IMAPISession MAPI 인터페이스 반환)을 캐시 한 다음 보조 스레드에서 RDOSession 개체의 인스턴스를 만들고 RDOSession.MAPIOBJECT 속성을 설정할 수 있습니다 기본 스레드에 저장된 값으로. RDOSession.GetMessageFromID를 사용하여 항목 ID로 항목을 열 수 있습니다.