Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/google-apps-script/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
获取共享Outlook日历事件C#_C#_Outlook_Calendar_Office Interop - Fatal编程技术网

获取共享Outlook日历事件C#

获取共享Outlook日历事件C#,c#,outlook,calendar,office-interop,C#,Outlook,Calendar,Office Interop,我知道如何在当前用户的outlook日历中检索事件,以下代码用于删除与特定模式匹配的项目,例如: private void RemoveAppointments() { Outlook.Application outlook = new Outlook.Application(); Outlook.MAPIFolder calendarFolder = outlook.Session.GetDefaultFolder(Outlook

我知道如何在当前用户的outlook日历中检索事件,以下代码用于删除与特定模式匹配的项目,例如:

private void RemoveAppointments()
        {
            Outlook.Application outlook = new Outlook.Application();
            Outlook.MAPIFolder calendarFolder = outlook.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderCalendar);
            Outlook.Items outlookCalendarItems = calendarFolder.Items;
            for (int i = outlookCalendarItems.Count; i > 0; i--)
            {
                if (outlookCalendarItems[i].Subject.Contains("On Call: Regions:") && outlookCalendarItems[i].Start.Year == _year)
                {
                    outlookCalendarItems[i].Delete();
                }
            }
        }
但是,我现在需要能够从Outlook团队中的所有用户处读取日历事件(假设已正确设置共享权限)。理想情况下,我需要能够对每个用户进行迭代,但如果我只获得所有事件的集合,然后可以按用户查询,这也就足够了

你知道我从哪里开始吗


注意:这是团队在Outlook日历窗格中的表示方式。修改了敏感细节


使用
名称空间.GetDefaultFolder
,而不是使用
名称空间.GetSharedDefaultFolder
,传递从
名称空间.CreateRecipient
返回的
收件人
对象


还要记住,在文件夹中的所有项目之间循环是一个可怕的想法,尤其是当您打开一个未缓存在本地OST文件中的在线文件夹时。使用
项。查找/FindNext
项。改为限制

不要使用
名称空间.GetDefaultFolder
,而是使用
名称空间.GetSharedDefaultFolder
,传递从
名称空间.CreateRecipient
返回的
收件人
对象

还要记住,在文件夹中的所有项目之间循环是一个可怕的想法,尤其是当您打开一个未缓存在本地OST文件中的在线文件夹时。使用
项。查找/FindNext
项。改为限制

感谢@Dmitry帮助我解决了问题。然而,为了使这个问题对未来读者的效用最大化,我想我会对此进行扩展


假设:

using Microsoft.Office.Interop.Outlook;
并且引用了COM程序集Microsoft Outlook 16.0对象库


第一步是创建一个
Outlook.Application
对象,作为Outlook功能的接口(您可以将其视为完整Outlook程序的内部实例):

然后,我从与团队关联的全局地址列表中的通讯组列表中提取所有用户。这是通过从
应用程序
实例的
会话
属性创建一个
收件人
对象来实现的

Recipient distList = app.Session.CreateRecipient(yourDistList);
从这里,我们可以提取收件人的
adresentry.Members
属性中的所有实名和用户名。要将这两个查询都拉入
(string,string)
的匿名元组中,我们可以使用此LINQ查询,如果您不喜欢,可以像正常情况一样进行迭代:

List<(string,string)> usersData = distList.AddressEntry.Members.Cast<AddressEntry>().Select(entry => (entry.Name,entry.Address)).ToList();
在这一点上,我发现做一些过滤来避免最常见的
COMException
s是很有用的。然而,有很多我似乎无法确定原因,所以我只是
catch(COMException)
并把它们扔掉。我知道这不是一个好的做法,但它似乎并没有妨碍我访问我有权限访问的日历。一些(非常)基本的过滤:

if (sharedCalendar.DefaultMessageClass != "IPM.Appointment" || teamMember.DisplayType != 0)
{
    return null; //Calendar not shared.
}
现在,我们必须使用Microsoft Outlook格式构建一个
过滤器
字符串,这可以使用以下语句来完成(其中
from
to
都是
DateTime
对象):

这将返回一个
Items
接口,该接口指向我们过滤器中的所有项

最后,我们可以迭代每个项目(我以相反的顺序进行迭代,因为我从我的一个旧应用程序复制了代码,该应用程序删除了事件,但在这个上下文中这不重要)。您可能必须将
对象
强制转换为
任命项
,具体取决于编译器是否可以推断出该对象

List<AppData> appointments = new List<AppData>();
for (int i = results.Count; i > 0; i--)
{
    appointments.Add(new AppData(results[i], username));
}

所有这些都会导致一个看起来像这样的类:

public class OutlookCommunicator : IDisposable
{
    private readonly Application _app;

    public OutlookCommunicator()
    {
        _app = new Application();
    }

    /// <summary>
    /// Username of the distribution list according to the GAL.
    /// </summary>
    private const string DistList = "redacted";

    /// <summary>
    /// Fetches a list of all usernames and names within the DistList.
    /// </summary>
    /// <returns>List&lt;string&gt; containing all usernames.</returns>
    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;

    }



    /// <summary>
    /// Fetches all calendar events for a user falling within the provided range.
    /// </summary>
    /// <param name="from">Start search date.</param>
    /// <param name="to">End search dat.</param>
    /// <param name="username">User's calendar to search.</param>
    /// <returns></returns>
    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; //Calendar not shared.
            }

            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();
    }
公共类了望通信器:IDisposable
{
私有只读应用程序_app;
公众了望台
{
_app=新应用程序();
}
/// 
///根据GAL的通讯组列表的用户名。
/// 
private const string DistList=“redacted”;
/// 
///获取DistList中所有用户名和名称的列表。
/// 
///包含所有用户名的Liststring。
公共列表GetUsers()
{
收件人工程=_app.Session.CreateRecipient(DistList);
List usernames=warEngineering.AddressEntry.Members.Cast().Select(entry=>(entry.Name,entry.Address)).ToList();
返回用户名;
}
/// 
///获取所提供范围内用户的所有日历事件。
/// 
///开始搜索日期。
///结束搜索数据。
///要搜索的用户日历。
/// 
公共列表GetEventsRange(日期时间从、日期时间到、字符串用户名)
{
列表约会=新列表();
尝试
{
收件人团队成员=_app.Session.CreateRecipient(用户名);
MAPIFolder sharedCalendar=\u app.Session.GetSharedDefaultFolder(团队成员,OldDefaultFolders.olFolderCalendar);
如果(sharedCalendar.DefaultMessageClass!=“IPM.Appointment”| | teamMember.DisplayType!=0)
{
返回null;//日历未共享。
}
字符串sFilter=$“[End]>'{from:g}'和[Start]<'{to:g}'和[recurtive]='No';
Items results=sharedCalendar.Items.Restrict(sFilter);
对于(int i=results.Count;i>0;i--)
{
添加(新的AppData(结果[i],用户名));
}
返回任命;
}
捕获(COMException)
{
返回null;
}
}
公共空间处置()
{
_app?.Quit();
}
多亏@Dmitry帮我解决了这个问题。不过,为了使这个问题对未来读者的效用最大化,我想我会对它进行扩展


假设:

using Microsoft.Office.Interop.Outlook;
并且引用了COM程序集Microsoft Outlook 16.0对象库


第一步是创建一个
输出
Items results = sharedCalendar.Items.Restrict(sFilter);
List<AppData> appointments = new List<AppData>();
for (int i = results.Count; i > 0; i--)
{
    appointments.Add(new AppData(results[i], username));
}
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();
    }

    /// <summary>
    /// Username of the distribution list according to the GAL.
    /// </summary>
    private const string DistList = "redacted";

    /// <summary>
    /// Fetches a list of all usernames and names within the DistList.
    /// </summary>
    /// <returns>List&lt;string&gt; containing all usernames.</returns>
    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;

    }



    /// <summary>
    /// Fetches all calendar events for a user falling within the provided range.
    /// </summary>
    /// <param name="from">Start search date.</param>
    /// <param name="to">End search dat.</param>
    /// <param name="username">User's calendar to search.</param>
    /// <returns></returns>
    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; //Calendar not shared.
            }

            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();
    }