Background . I am writing a C # application (.NET 3.5) that scans multiple Outlook 2003 calendars (using COM objects), receives appointments, and inserts the data for these appointments into a database.
Problem: After the first user calendar, any duplicate elements in the following calendars will always have the beginning and end of the first occurrence of this element. I am releasing COM objects between users (and during, if the user has many elements), and the collection of elements is limited correctly (due to the fact that only a few repeated tasks are inserted into it (although the start / end is incorrect) instead of the endless task " without end "). The correct start / end time is part of the requirements, having the information available for this or another application to determine how much free time the user has for a given date range and working time.
Code: (variable declarations are not specified, they are at the top of the corresponding functions)
Quoting through users (in Main ()):
foreach (DataRow drUserCalendar in dtCalendars.Rows) {
Retrieving Calendar Information
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 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 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"); } }