2011-12-02 58 views
4

背景:我在C#(.NET 3.5)中編寫一個應用程序,該應用程序查看多個用戶Outlook 2003日曆(使用COM對象),獲取約會並將這些約會的數據插入數據庫。Outlook 2003 - 顯示首次出現的重複項目開始/結束日期

問題:在第一個用戶日曆之後,下列日曆中的任何重複項目始終會有該項目第一次出現的開始和結束時間。我發佈了用戶之間的COM對象(並且在用戶有很多項目的情況下),並且正在限制項目集合(由於只有少數插入的重複任務(儘管錯誤的開始/結束)而不是無限的「無盡」任務)。正確的開始/結束時間是需求的一部分,讓這個或另一個應用程序可用這些信息計算出用戶在給定的日期範圍和工作時間內有多少空閒時間。

代碼:(變量聲明省略,他們在相關功能上)

通過用戶循環(在main()):

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

測試後,我發現,這個問題涉及到我的(或誰運行的應用程序)的用戶權限(共享),日曆(S)正在看着。

它適用於第一個用戶,因爲這是我自己的情況。這對用戶來說不起作用,因爲我似乎沒有足夠的權限(通過讓我的同事更改它以確保默認用戶是他的日曆上的「所有者」並再次運行該應用程序,並且它爲他的日曆工作) 。

我自從嘗試使用GetOccurrence(DateTime)(包含一段while循環),但是這導致了相同的問題。當沒有發生(如預期的)時,該函數會出錯,但是當它發現一個事件時,它會返回一個空對象。然而,因爲除了獲取任務的開始和結束日期之外,我沒有使用任何對象,所以我手工完成了它(我有原始任務,這意味着我可以通過每天遞增來獲得持續時間直到我得到一個事件,我會得到循環任務的開始日期,並使用我計算結束日期的任務的持續時間)。

這不是一個理想的解決方案,但如果你只是想要得到重複的任務它足夠簡單的事(不過,如果你有很多的reccurring任務,並循環用於長期資源消耗)

+0

也許試試Redemption(我相信那裏是一個試驗)。我遇到了與Exceptions集合類似的問題,但打開RDOAppointmentItem並使用RDO(而不是OOM)和問題「解決了」(當然,這也意味着我可能也會微妙地RCW泄漏)。也許有類似的真棒給你... – 2011-12-22 05:49:58

0

我看不出你的代碼有一個明顯的問題我害怕,但正如我期望你很清楚有可能有一些其他發生在幕後的事情正在引發你的問題。

我在一篇博客文章 - http://jynxeddevelopment.blogspot.com中使用這些內容時,發現了一些最佳實踐。可能值得一讀,看看有什麼東西看起來與你在做什麼不一樣,我認爲「保持所有內容的參考」部分可能是有用的。

我不知道你的COM對象將與廣播呼叫,你不是要設置他們先爲空,但無論哪種方式,這不應該有所作爲收集。沒有任何GC調用,我得到了這種工作。

事情來看待:

  • objOne應該是釋放的每一個循環,如果它是一個COM對象(我希望它是)
  • 釋放它之前關閉您的Outlook應用程序(appOutlook.Close()),我很驚訝,你沒有得到很多人掛在
  • 檢查您正在使用的COM對象的每一個領域,如果他們是COM對象了,他們可能需要敲定太

很抱歉,這沒有什麼具體的東西,但是用這些東西來工作很難:/祝你好運!

-Jynx

+0

感謝您的回覆。 Unfroututnatly我釋放所有被調用的COM對象。之後,我打電話給GC之前,我已經對他們進行了無效處理。在釋放,清零和調用GC之前,我還在Outlook對象上調用了Quit方法(我在之前的版本中,但它證明通過關閉我的前景使我煩惱......) – Phen

相關問題