有没有办法从所有 Outlook 的共享日历中检索事件(约会)?

Is there a way to retrieve events (appointments) from all Outlook's shared calendars?

我的问题是,我无法访问和迭代 Outlook 的共享日历。我尝试了几种方法,但它们都将我带回默认日历(即我的帐户日历)。

我尝试在子文件夹中循环,使用 GetSharedDefaultFolder() 方法并使用 Interop 库的不同类型的对象,但我无法解决它。

Here are the methods I've tried. To run the program (in particular GetMethod3() and GetMethod5()) you have to set the string "email" with your own email.

using System;
using System.Text;
using Microsoft.Office.Interop.Outlook;

namespace OutlookTest {
    class Program {

        static void Main(string[] args) {

            OutlookSharedCalendar outlookSharedCalendar = new OutlookSharedCalendar();

        }
    }

    public class OutlookSharedCalendar{

        Microsoft.Office.Interop.Outlook.Application oApp;
        NameSpace oNameSpace = null;
        MAPIFolder oMAPIFolder = null;
        MAPIFolder objFolder = null;
        MAPIFolder objSubFolder = null;
        Explorer objExplorer;
        AppointmentItem objCalenderItem;
        Folders objOutlookFolders;
        AddressEntry addrEntry = null;
        Items oCalendarItems = null;
        string email = "myemail@email.com";

        public OutlookSharedCalendar() {

            AppStart();
            GetMethod1();
            AppEnd(); 

            AppStart();
            GetMethod2();
            AppEnd();

            AppStart();
            GetMethod3();
            AppEnd();

            AppStart();
            GetMethod4();
            AppEnd();

            AppStart();
            GetMethod5();
            AppEnd();
        }

        public void GetMethod1() {
            oMAPIFolder = oApp.Session.GetDefaultFolder(OlDefaultFolders.olFolderCalendar);
            oCalendarItems = (Items)oMAPIFolder.Items;
            oCalendarItems.IncludeRecurrences = true;
            foreach(AppointmentItem item in oCalendarItems) {

                if(item.IsRecurring) {

                    RecurrencePattern oRP = item.GetRecurrencePattern();
                    DateTime first = new DateTime(2018, 01, 01, item.Start.Hour, item.Start.Minute, 0);
                    DateTime last = new DateTime(2019, 10, 31);
                    AppointmentItem recur = null;

                    for(DateTime cur = first; cur <= last; cur = cur.AddDays(1)) {
                            recur = oRP.GetOccurrence(cur);
                            Console.WriteLine(recur.Subject + " - " + cur.ToLongDateString() + " - " + recur.Body);
                    }
                }
                else {
                    Console.WriteLine(item.Subject + " -> " + item.Start.ToLongDateString());
                }
            }
        }

        public void GetMethod2() {
            int intFolderCtr;
            int intSubFolderCtr;
            int intAppointmentCtr;
            // >> Initialize The Base Objects
            objOutlookFolders = oApp.Session.Folders;
            // >> Loop Through The PST Files Added n Outlook
            for(intFolderCtr = 1; intFolderCtr <= objOutlookFolders.Count; intFolderCtr++) {
                objFolder = objOutlookFolders[intFolderCtr];
                objExplorer = objFolder.GetExplorer();
                // >> Loop Through The Folders In The PST File
                for(intSubFolderCtr = 1; intSubFolderCtr <= objExplorer.CurrentFolder.Folders.Count; intSubFolderCtr++) {
                    objSubFolder = objExplorer.CurrentFolder.Folders[intSubFolderCtr];
                    // >> Check if Folder Contains Appointment Items
                    if(objSubFolder.DefaultItemType == OlItemType.olAppointmentItem) {
                        // >> Loop Through Appointment Items
                        for(intAppointmentCtr = 1; intAppointmentCtr <= objSubFolder.Items.Count; intAppointmentCtr++) {
                            // >> Get Teh Calender Item From The Calender Folder
                            objCalenderItem = objSubFolder.Items[intAppointmentCtr];
                            // >> Process Appointment Item Accordingly
                            Console.WriteLine(objCalenderItem.Subject + " - " + objCalenderItem.Start + " - " + objCalenderItem.Body + " - " + objCalenderItem.Location);
                        }
                    }
                }
            }
        }

        public void GetMethod3() {

            DateTime dtFrom = new DateTime(DateTime.Now.Year, 01, 01);
            DateTime dtTo = new DateTime(DateTime.Now.Year, 12, 31);

            Recipient teamMember = oApp.Session.CreateRecipient(email);
            MAPIFolder sharedCalendar = oApp.Session.GetSharedDefaultFolder(teamMember, OlDefaultFolders.olFolderCalendar);
            if(sharedCalendar.DefaultMessageClass != "IPM.Appointment" || teamMember.DisplayType != 0) {
                return; //Calendar not shared.
            }

            string restrictCriteria = "[Start]<=\"" + dtTo.ToString("g") + "\"" + " AND [End]>=\"" + dtFrom.ToString("g") + "\"";

            Items results = sharedCalendar.Items.Restrict(restrictCriteria);

            foreach(AppointmentItem item in results) {
                Console.WriteLine(item.Subject + " - " + item.Start + " - " + item.Body + " - " + item.Location);
            }
        }

        public void GetMethod4() {

            oMAPIFolder = oApp.Session.GetDefaultFolder(OlDefaultFolders.olFolderCalendar);

            DateTime dtEnd = new DateTime(DateTime.Now.Year, 12, 31);
            DateTime dtStart = new DateTime(DateTime.Now.Year, 01, 01);
            string restrictCriteria = "[Start]<=\"" + dtEnd.ToString("g") + "\"" +
                                      " AND [End]>=\"" + dtStart.ToString("g") + "\"";
            StringBuilder strBuilder = null;
            Items folderItems = null;
            Items resultItems = null;
            AppointmentItem appItem = null;
            int counter = default(int);
            object item = null;

            strBuilder = new StringBuilder();
            folderItems = (Items)oMAPIFolder.Items;
            folderItems.IncludeRecurrences = true;
            folderItems.Sort("[Start]");
            resultItems = folderItems.Restrict(restrictCriteria);
            item = resultItems.GetFirst();
            do {
                if(item != null) {
                    if(item is AppointmentItem) {
                        counter++;
                        appItem = item as AppointmentItem;
                        Console.WriteLine(appItem.Subject + " -> " + appItem.Start.ToLongDateString());
                        strBuilder.AppendLine("#" + counter.ToString() +
                                              "\tStart: " + appItem.Start.ToString() +
                                              "\tSubject: " + appItem.Subject +
                                              "\tLocation: " + appItem.Location);
                    }
                    item = resultItems.GetNext();
                }
            }
            while(item != null);
        }

        public void GetMethod5() {

            addrEntry = oApp.Session.CurrentUser.AddressEntry;
            if(addrEntry.Type == "EX") {
                Recipient recip = oApp.Session.CreateRecipient(email);
                if(recip.Resolve()) {
                    Folder folder = oApp.Session.GetSharedDefaultFolder(recip, OlDefaultFolders.olFolderCalendar) as Folder;
                    foreach(AppointmentItem item in folder.Items) {

                        Console.WriteLine(item.Subject + " - " + item.Start + " - " + item.Body + " - " + item.Location);

                    }
                }
            }
        }

            public void AppStart() {

            // >> Start Outlook
            oApp = new Microsoft.Office.Interop.Outlook.Application();
        }
            public void AppEnd() {

            // >> Close Application
            oApp.Quit();
            // >> Release COM Object
            System.Runtime.InteropServices.Marshal.ReleaseComObject(oApp);
            oApp = null;

        }

    }
}

我希望我能得到关于代码的建议,或者如果有人知道 Interop 的可行替代方案。提前谢谢大家。

NameSpace.GetSharedDefaultFolder 方法用于获取表示指定用户的指定默认文件夹的Folder 对象。例如,稍作改动:

public void GetMethod3() {

    DateTime dtFrom = new DateTime(DateTime.Now.Year, 01, 01);
    DateTime dtTo = new DateTime(DateTime.Now.Year, 12, 31);

    Recipient teamMember = oApp.Session.CreateRecipient(email);
    teamMember.Resolve();
    if(teamMember.Resolved)
    { 
       MAPIFolder sharedCalendar = oApp.Session.GetSharedDefaultFolder(teamMember, OlDefaultFolders.olFolderCalendar);
       if(sharedCalendar.DefaultMessageClass != "IPM.Appointment" || teamMember.DisplayType != 0) {
           return; //Calendar not shared.
       }

       string restrictCriteria = "[Start]<=\"" + dtTo.ToString("g") + "\"" + " AND [End]>=\"" + dtFrom.ToString("g") + "\"";

       Items results = sharedCalendar.Items.Restrict(restrictCriteria);

       foreach(AppointmentItem item in results) {
          Console.WriteLine(item.Subject + " - " + item.Start + " - " + item.Body + " - " + item.Location);
       }
    }
}

如您所见,在尝试访问共享日历之前,收件人应该根据您的地址簿进行解析。 Recipient.Resolve 方法尝试根据地址簿解析 Recipient 对象。