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