Outlook 2003 -显示首次出现的开始/结束日期的循环项目

本文关键字:开始 结束 日期 项目 循环 2003 显示 Outlook | 更新日期: 2023-09-27 18:16:42

Background:我正在用c#编写一个应用程序。. NET 3.5),它查看多个用户Outlook 2003日历(使用COM对象),获取约会并将这些约会的数据插入数据库。

问题:在第一个用户日历之后,任何在后续日历中重复出现的项目,将始终具有该项目第一次出现的开始和结束时间。我在用户之间释放COM对象(如果用户有很多项目),并且项目收集被正确限制(由于只有少数重复插入的任务(尽管错误的开始/结束),而不是无限的"无结束"任务)。正确的开始/结束时间是需求的一部分,为这个或另一个应用程序提供可用的信息,以计算出用户在给定的日期和工作时间范围内有多少空闲时间。

代码:(省略变量声明,它们位于相关函数的顶部)

遍历用户(in 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");
            }
        }

Outlook 2003 -显示首次出现的开始/结束日期的循环项目

我看不出你的代码有什么明显的问题,但正如我所期望的那样,你很可能知道幕后发生了一些其他的事情,导致了你的问题。

我已经在一篇博客文章- http://jynxeddevelopment.blogspot.com中介绍了一些我在处理这些东西时发现的最佳实践。这可能值得一读,看看是否有什么东西似乎与你正在做的不同,我认为"保持引用一切"这一节可能会有用。

我不确定你的COM对象会被GC调用收集,因为你没有首先将它们设置为null,但是无论哪种方式,这都不应该有什么不同。我让这类事情不需要任何GC调用就能工作。

注意事项:

  • objOne应该释放每个循环,如果它是一个COM对象(我希望它是)
  • 在发布Outlook应用程序之前关闭它(appOutlook.Close()),我很惊讶你没有得到很多他们闲逛
  • 检查你在COM对象上使用的每个字段,如果它们也是COM对象,它们可能也需要finalize

对不起,这是没有具体的,但工作与这些东西是艰苦的工作:/祝你好运!

-Jynx

经过测试,我发现这个问题与我(或任何运行应用程序的人)对正在查看的用户(共享)日历的权限有关。

它对第一个用户起作用,因为在这个例子中,这个用户就是我自己。在那之后,它对用户不起作用,因为我似乎没有足够的权利(通过让我的同事更改它来确认,因此默认用户是他日历上的"所有者"并再次运行应用程序,并且它为他的日历工作)。

我已经尝试使用GetOccurrence(DateTime)(被一个while循环包围),但是这会导致同样的问题。当没有出现时(如预期的那样),该函数将出错,但当发现出现时,它将返回一个空对象。

然而,因为我没有使用对象来获取任务的开始和结束日期,所以我手动计算出它(我有原始任务,这意味着我可以获得持续时间,通过每天增加,直到我得到一个事件,我将得到循环任务的开始日期,并使用任务的持续时间我计算结束日期)。

这不是一个理想的解决方案,但如果你只是想要得到循环的任务,这是足够简单的(虽然如果你有很多循环的任务和很长一段时间的资源消耗)