感谢@Dmitry
his answer
这帮我解决了我的问题。然而,为了最大限度地利用这个问题为未来的读者,我想我会扩大它。
假设:
using Microsoft.Office.Interop.Outlook;
COM程序集
Microsoft Outlook 16.0 Object Library
Outlook.Application
对象,该对象用作Outlook函数的接口(可以将其视为完整Outlook程序的内部实例):
Application app = new Application();
然后,我从与团队关联的全局地址列表的通讯组列表中提取所有用户。这是通过创建
Recipient
对象来自
Session
Application
实例。
Recipient distList = app.Session.CreateRecipient(yourDistList);
从这里我们可以把所有的实名和用户名
AdressEntry.Members
收件人的财产。把这两个放入
(string,string)
List<(string,string)> usersData = distList.AddressEntry.Members.Cast<AddressEntry>().Select(entry => (entry.Name,entry.Address)).ToList();
现在,给定一个特定的用户名,只要日历已经与curernt用户共享,就可以使用
GetSharedDefaultFolder()
方法
会议
:
MAPIFolder sharedCalendar = _app.Session.GetSharedDefaultFolder(teamMember, OlDefaultFolders.olFolderCalendar);
在这一点上,我发现做一些过滤来避免最常见的
COMException
但是,有很多我似乎无法确定的原因,所以我只是
catch (COMException)
把它们扔掉。我知道这不是一个好的做法,但它似乎不会妨碍我访问我有权限访问的日历。一些(非常)基本的过滤:
if (sharedCalendar.DefaultMessageClass != "IPM.Appointment" || teamMember.DisplayType != 0)
{
return null; //Calendar not shared.
}
现在我们必须建立一个
Filter
字符串使用Microsoft Outlook格式,可以使用以下语句(其中
from
和
to
两者都是
DateTime
string sFilter = $"[End] > '{from:g}' AND [Start] < '{to:g}' AND [Recurring] = 'No'";
我们过滤掉重复发生的事件,否则开始和结束日期可能会大大超出范围,而不会出现内部事件。出于我的目的,我不需要经常性的事件,但是,如果你这样做,你将不得不单独处理这个。
最后,我们现在可以利用
Items.Restrict()
方法
MAPIFolder
Items results = sharedCalendar.Items.Restrict(sFilter);
这将返回
Items
接口到属于我们过滤器的所有项。
最后,我们可以对每个项进行迭代(我以相反的顺序迭代,因为我从我的旧应用程序中复制了删除事件的代码,但在这种情况下这不重要)。你可能得把
object
到
AppointmentItem
List<AppData> appointments = new List<AppData>();
for (int i = results.Count; i > 0; i--)
{
appointments.Add(new AppData(results[i], username));
}
我将每个事件存储为
AppData
结构只保留我需要的数据:
public struct AppData
{
public string Subject { get; }
public DateTime From { get; }
public DateTime To { get; }
public string Location { get; }
public string Categories { get; }
public string Username { get; }
public AppData(AppointmentItem appItem, string username)
{
Subject = appItem.Subject;
From = appItem.Start;
To = appItem.End;
Location = appItem.Location;
Categories = appItem.Categories;
Username = username;
}
}
所有这些都会产生这样一个类:
public class OutlookCommunicator : IDisposable
{
private readonly Application _app;
public OutlookCommunicator()
{
_app = new Application();
}
private const string DistList = "redacted";
public List<(string,string)> GetUsers()
{
Recipient warEngineering = _app.Session.CreateRecipient(DistList);
List<(string,string)> usernames = warEngineering.AddressEntry.Members.Cast<AddressEntry>().Select(entry => (entry.Name,entry.Address)).ToList();
return usernames;
}
public List<AppData> GetEventsInRange(DateTime from, DateTime to, string username)
{
List<AppData> appointments = new List<AppData>();
try
{
Recipient teamMember = _app.Session.CreateRecipient(username);
MAPIFolder sharedCalendar = _app.Session.GetSharedDefaultFolder(teamMember, OlDefaultFolders.olFolderCalendar);
if (sharedCalendar.DefaultMessageClass != "IPM.Appointment" || teamMember.DisplayType != 0)
{
return null;
}
string sFilter = $"[End] > '{from:g}' AND [Start] < '{to:g}' AND [Recurring] = 'No'";
Items results = sharedCalendar.Items.Restrict(sFilter);
for (int i = results.Count; i > 0; i--)
{
appointments.Add(new AppData(results[i], username));
}
return appointments;
}
catch (COMException)
{
return null;
}
}
public void Dispose()
{
_app?.Quit();
}