2011-12-02 2 views
4

배경 : COM 개체를 사용하여 여러 사용자 Outlook 2003 일정을 보는 C# (.NET 3.5) 응용 프로그램을 작성하고 약속에 대한 데이터를 데이터베이스에 삽입합니다.Outlook 2003 - 첫 번째 항목 시작/끝 날짜가 반복되는 항목

문제점 : 첫 번째 사용자 일정 관리 이후에 다음 일정 항목의 반복 항목에는 항상 해당 항목의 첫 번째 항목의 시작 및 종료 시간이 있습니다. 나는 사용자들 사이에 (그리고 사용자가 많은 아이템을 가지고있을 때) COM 객체를 발표 할 것이고, 아이템 컬렉션은 정확하게 제한되어있다. (몇 가지 반복 태스크가 삽입 되었기 때문에 (잘못된 시작/"무한"대신 "무한"대신에 "끝"). 올바른 시작/종료 시간은 요구 사항의 일부이며,이 응용 프로그램 또는 다른 응용 프로그램이 주어진 날짜 범위 및 근무 시간 동안 자유 시간을 얼마나 사용할 수 있는지에 대한 정보가 있습니다.

코드 :() (홈페이지에서) 사용자를 통해 반복

(변수 선언은 관련 기능의 상단에있어 생략) :

foreach (DataRow drUserCalendar in dtCalendars.Rows) 
       { 
        //for each calendar we're looking at, export their calendar data and put it in the database 
        try 
        { 
         appOutlook = new Outlook.Application(); 
         ExportCalendar(drUserCalendar); 
         Marshal.FinalReleaseComObject(appOutlook); 
         GC.Collect(); 
        } 
        catch (Exception ex) 
        { 
         //report error 
        } 
       } 

으로부터 정보를 추출 캘린더

static void ExportCalendar(DataRow drUser) 
     {      
      strDisplayName = drUser["DisplayName"].ToString(); 
      strUserID = drUser["ID"].ToString(); 

      int.TryParse(drUser["PreviousDays"].ToString(), out intPrevious); 
      int.TryParse(drUser["FutureDays"].ToString(), out intFuture); 

      dtmAllowedPreviousStart = DateTime.Now.AddDays(-intPrevious); 
      dtmAllowedFutureStart = DateTime.Now.AddDays(intFuture); 

      nsOne = appOutlook.GetNamespace("MAPI"); 
      nsOne.Logon(null, null, false, false); 
      rcpOne = nsOne.CreateRecipient(strDisplayName); 

      intCount = 0; 

      if (rcpOne.Resolve()) 
      { 
       fldOne = nsOne.GetSharedDefaultFolder(rcpOne, Outlook.OlDefaultFolders.olFolderCalendar); 

       strRestrict = "[Start] > '" + MIN_START_DATE.ToString("g") + "' And [End] < '" + MAX_START_DATE.ToString("g") + "'"; 
       itms = fldOne.Items; 
       itms.Sort("[Start]", Type.Missing); 
       itms.IncludeRecurrences = true; 
       itmsRestricted = itms.Restrict(strRestrict); 
       itmsRestricted.Sort("[Start]", Type.Missing); 
       itmsRestricted.IncludeRecurrences = true; 
       blnIsRecurring = false; 
       dicRecurringTaskTracker = new Dictionary<string, int>(); 

       foreach (object objOne in itmsRestricted) 
       { 

        if (intCount >= 100 || blnIsRecurring) 
        { 
         //release COM objects. Outlook doesn't like you having more than 250 ish items without cleaning up. 
         Marshal.FinalReleaseComObject(appOutlook); 
         appOutlook = new Outlook.Application(); 
         GC.Collect(); 
         intCount = 0; 
        } 

        if (objOne is Outlook.AppointmentItem) 
        { 
         appItem = (Outlook.AppointmentItem)objOne; 
         blnException = false; 

         //get data from the item 
         strEntryID = appItem.EntryID; 
         strSubject = appItem.Subject; 
         strBody = appItem.Body; 
         dtmStart = appItem.Start; 
         dtmEnd = appItem.End; 

         blnException = EXCEPTIONS.Contains(strSubject); 

         //if the item is an exception we're done with it. 
         if (!blnException) 
         { 
          strRecurrenceInterval = ""; 
          strRecurrenceType = ""; 
          strRecurrenceInfo = ""; 


          //check if it's a recurring task. 
          blnIsRecurring = appItem.IsRecurring; 
          if (blnIsRecurring) 
          { 
           //check to see if we've already had a task from this series 
           if (!dicRecurringTaskTracker.Keys.Contains(strEntryID)) 
           { 
            //Start at 0 so the first (this) task 
            //is number 1. 
            dicRecurringTaskTracker.Add(strEntryID, 0); 
           } 

           //update number 
           dicRecurringTaskTracker[strEntryID] += 1; 
           //change the subject to add the count on the end 
           strEntryID = strEntryID + '-' + dicRecurringTaskTracker[strEntryID].ToString(); 

           //it's a recurring task, so we need to find out when/how often. 
           rpTaskRecurrence = appItem.GetRecurrencePattern(); 
           rtTaskRecurrenceType = rpTaskRecurrence.RecurrenceType; 
           strRecurrenceType = rtTaskRecurrenceType.ToString(); 
           strRecurrenceInterval = rpTaskRecurrence.Interval.ToString(); 

           switch (strRecurrenceType) 
           { 
            case "olRecursDaily": 
            case "olRecursMonthNth": 
            case "olRecursWeekly": 
             strRecurrenceInfo = rpTaskRecurrence.DayOfWeekMask.ToString(); 
             break; 
            case "olRecursMonthly": 
             strRecurrenceInfo = rpTaskRecurrence.DayOfMonth.ToString(); 
             break; 
           } 
          } 

          if (strEntryID != null && strSubject != null && dtmStart != null && dtmEnd != null 
           && (intPrevious == 0 || (dtmStart > dtmAllowedPreviousStart)) && (intFuture == 0 || (dtmStart < dtmAllowedFutureStart))) 
          { 
           //build up the SQL 
           strSQL = "EXEC UpdateCalendarEntry "; 
           strSQL += "@EntryID='" + strEntryID + "', "; 
           strSQL += "@Subject='" + strSubject.Replace("'", "''") + "', "; 
           strSQL += "@Body='" + strSubject.Replace("'", "''") + "', "; 
           strSQL += "@StartDate='" + dtmStart.ToString("dd-MMM-yyyy HH:mm:ss") + "', "; 
           strSQL += "@EndDate='" + dtmEnd.ToString("dd-MMM-yyyy HH:mm:ss") + "', "; 
           strSQL += "@UserCalendarID=" + strUserID + ","; 
           strSQL += "@Recurring = " + blnIsRecurring.ToString() + ","; 
           strSQL += "@RecurrenceType = '" + strRecurrenceType + "',"; 
           strSQL += "@RecurrenceInterval = '" + strRecurrenceInterval + "',"; 
           strSQL += "@RecurrenceInfo = '" + strRecurrenceInfo + "';"; 

           try 
           { 
            //Execute SQL 
           } 
           catch (Exception ex) 
           { 
            //Print error message 
            MessageBox.Show(ex.ToString()); 
           } 
          } 
         } 
         Marshal.FinalReleaseComObject(appItem); 
         GC.Collect(); 
        } 
        strEntryID = null; 
        strSubject = null; 
        strBody = null; 
        intCount++; 
       } 

       //finished looping, do some clean up. 
       Marshal.FinalReleaseComObject(nsOne); 
       Marshal.FinalReleaseComObject(rcpOne); 
       Marshal.FinalReleaseComObject(fldOne); 
       Marshal.FinalReleaseComObject(itms); 
       Marshal.FinalReleaseComObject(itmsRestricted); 
       GC.Collect(); 
      } 
      else 
      { 
       throw new Exception("Could not resolve name"); 
      } 
     } 

답변

0

은 (공유) 일정 (들)에보고되고 있음.

첫 번째 사용자는이 경우 자체적으로 작동하기 때문에 첫 번째 사용자에게만 작동합니다.충분한 권한이 없기 때문에 그 이후에는 사용자가 작동하지 않습니다 (내 동료가 기본 사용자를 변경하여 자신의 캘린더에서 "소유자"가되어 응용 프로그램을 다시 실행하고 자신의 캘린더에서 작업하는 것으로 확인 됨) .

나는 그 이후로 같은 문제로 이어지는 GetOccurrence(DateTime) (while 루프로 둘러 쌓여 있음)을 사용하려고 시도했습니다. 이 함수는 (예상 한대로) 아무런 발생도 없었을 때 오류가되지만, 발생을 발견하면 null 객체를 반환합니다.

그러나 작업의 시작 날짜와 종료 날짜를 얻는 것 이외의 다른 개체를 사용하지 않았기 때문에 수동으로 작업했습니다 (원래 작업이 있었기 때문에 매일 작업을 늘릴 수 있음). 사건이 발생할 때까지 반복되는 작업 시작 날짜를 얻고 작업의 지속 시간을 사용하여 종료 날짜를 계산했습니다.)

그것은 이상적인 솔루션 아니지만, 당신은 그것을 할 수있을만큼 단순 반복 작업을 취득하고자하는 경우

(당신이 반복적으로 발생하는 작업을 많이 가지고 오랜 기간 동안 반복되는 경우 자원이 소모하지만)
+0

아마도 Redemption을 시도 할 것이다. 재판이다). 예외 컬렉션과 비슷한 문제가 있었지만 RDOAppointmentItem을 열고 RDOM (OOM이 아님)을 사용하고 문제가 "해결되었습니다"(물론 이것은 또한 미묘한 RCW 유출이있을 수 있음을 의미합니다). 어쩌면 당신을위한 비슷한 awesomeness가있을 것입니다 ... –

0

코드에 명백한 문제가 표시되지 않을 수 있습니다. 두렵지 만 잘 알고 있기를 바랍니다. 문제를 일으키는 장면 뒤에서 일어나는 다른 일들.

블로그 기사에서이 자료로 작업 할 때 우수 사례로 밝혀진 몇 가지 사항을 다루었습니다. http://jynxeddevelopment.blogspot.com. 당신이하고있는 것과는 다른 것이 있는지보기 위해 읽을 가치가있을 것입니다. '모든 것을 참고하십시오'섹션이 유용 할 것 같습니다.

GC 개체를 처음으로 null로 설정하지 않아도 COM 개체를 수집 할 수 있을지 모르겠지만 두 방법 모두 차이가 없어야합니다. GC 호출 없이도 이런 종류의 작업을 할 수 있습니다.

  • objOne 그것이 COM 객체 (나는 그것이 기대)
  • 그것을 해제하기 전에 귀하의 Outlook 응용 프로그램을 닫기의 경우 매주 루프를 해제해야한다, (appOutlook.Close을())에

    상황이보고하기 나는 당신이 그들 중 많은 사람들이 COM 너무 그들도

이 죄송 마무리해야 할 수도 있습니다 개체를하는 경우, 당신은 COM 객체를 사용하는 모든 분야를 검사 주위

  • 매달려받지 놀랐어요 구체적인 것은 아니지만이 재료로 작업하는 것은 어려운 작업입니다./행운을 빌어 요! 나는 문제가 사용자에 내 (또는 누구든지 응용 프로그램을 실행) 권한에 관련된 것으로 나타났습니다 테스트 후

    -Jynx

  • +0

    답장을 보내 주셔서 감사합니다. Unfroututnatly 나는 호출되는 모든 COM 개체를 공개합니다. 나는 그 이후로 GC를 호출하기 전에 그것들을 없앴습니다. 나는 또한 이전에 outlook 객체에 Quit 메소드를 호출하여 null을 설정하고 GC를 호출했다. (이전 버전에서 였지만 내 전망을 닫아서 나를 귀찮게했다.) – Phen

    관련 문제