using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using Outlook = Microsoft.Office.Interop.Outlook; namespace MeetingClock { public class OutlookManager { private Outlook.Application application; public OutlookManager() { } public async Task GetNextAppointment( bool ignoreAllDayEvents, bool ignoreCancelledMeetings, bool ignoreFreeMeetings, bool ignoreOutOfOfficeMeetings, bool ignoreTentativeMeetings) { await Task.Run(() => { lock(this) { int retries = 5; while (this.application == null && retries-- > 0) { try { this.application = new Outlook.Application(); } catch (Exception exception) { this.application = null; Debug.WriteLine(String.Format("Failed to start outlook application: {0}", exception.Message)); Thread.Sleep(3000); } } } }); List appointmentItems = new List(); lock (this) { if (this.application == null) { return null; // not available at the moment } try { Outlook.Folder calendarFolder = this.application.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderCalendar) as Outlook.Folder; DateTime start = DateTime.Now; DateTime end = start.AddHours(2); string filter = String.Format("[Start] >= '{0}' AND [Start] <= '{1}'", start.ToString("g"), end.ToString("g")); Debug.WriteLine(String.Format("Filtering Outlook Events: {0}", filter)); Outlook.Items appointments = calendarFolder.Items; appointments.IncludeRecurrences = true; appointments.Sort("[Start]", Type.Missing); Outlook.Items filteredAppointments = appointments.Restrict(filter); Debug.WriteLine(String.Format("Found {0} outlook appointments between {1} and {2}", filteredAppointments.Count, start.ToString("g"), end.ToString("g"))); DateTime? firstAppointmentTime = null; foreach (Outlook.AppointmentItem appointment in filteredAppointments) { Debug.WriteLine(String.Format("{0}-{5} ({6}): {1} ({2}), allday: {3}, busy: {4}, importance: {7}, recurring: {8}, scheduled: {9}, conflict: {10}", appointment.Start.ToString("g"), appointment.Subject, appointment.MeetingStatus, appointment.AllDayEvent, appointment.BusyStatus, appointment.End.ToString("g"), appointment.Duration, appointment.Importance, appointment.RecurrenceState, appointment.CreationTime.ToString("g"), appointment.IsConflict)); if (ignoreAllDayEvents && appointment.AllDayEvent) { continue; // ignore all day events } if (ignoreCancelledMeetings && (appointment.MeetingStatus == Outlook.OlMeetingStatus.olMeetingCanceled || appointment.MeetingStatus == Outlook.OlMeetingStatus.olMeetingReceivedAndCanceled)) { continue; // ignore cancelled meetings } if (ignoreFreeMeetings && appointment.BusyStatus == Outlook.OlBusyStatus.olFree) { continue; // ignore free meetings } if (ignoreOutOfOfficeMeetings && appointment.BusyStatus == Outlook.OlBusyStatus.olOutOfOffice) { continue; // ignore out of office meetings } if (ignoreTentativeMeetings && appointment.BusyStatus == Outlook.OlBusyStatus.olTentative) { continue; // ignore tentative meetings } if (firstAppointmentTime == null) { firstAppointmentTime = appointment.Start; } // ignore appointments that do not start first if (firstAppointmentTime < appointment.Start) { continue; // ignore later appointments } appointmentItems.Add(appointment); Debug.WriteLine(String.Format("Next possible appointment is {0}-{1}: {2}", appointment.Start.ToString("t"), appointment.End.ToString("t"), appointment.Subject)); } } catch (Exception exception) { Debug.WriteLine(String.Format("Exception getting outlook appointments: {0}", exception.Message)); this.application = null; } } if (appointmentItems.Count == 0) { return null; // no appointments upcoming } if (appointmentItems.Count == 1) { return appointmentItems[0]; // exactly one appointment upcoming } // remove cancelled events appointmentItems = appointmentItems.AsQueryable() .Where(item => item.MeetingStatus != Outlook.OlMeetingStatus.olMeetingCanceled && item.MeetingStatus != Outlook.OlMeetingStatus.olMeetingReceivedAndCanceled).ToList(); if (appointmentItems.Count == 1) { return appointmentItems[0]; // one appointment still left } // remove duplicates by priority, select highest priority Outlook.OlImportance importance = appointmentItems.AsQueryable().OrderByDescending(item => (int)item.Importance).Select(item => item.Importance).First(); appointmentItems = appointmentItems.AsQueryable().Where(item => item.Importance == importance).ToList(); if (appointmentItems.Count == 1) { return appointmentItems[0]; // one appointment still left } // remove all day events appointmentItems = appointmentItems.AsQueryable().Where(item => !item.AllDayEvent).ToList(); if (appointmentItems.Count == 1) { return appointmentItems[0]; // one appointment still left } // remove free appointment appointmentItems = appointmentItems.AsQueryable().Where(item => item.BusyStatus != Outlook.OlBusyStatus.olFree).ToList(); if (appointmentItems.Count == 1) { return appointmentItems[0]; // one appointment still left } // remove tentative appointment appointmentItems = appointmentItems.AsQueryable().Where(item => item.BusyStatus != Outlook.OlBusyStatus.olTentative).ToList(); if (appointmentItems.Count == 1) { return appointmentItems[0]; // one appointment still left } // remove out of office appointment appointmentItems = appointmentItems.AsQueryable().Where(item => item.BusyStatus != Outlook.OlBusyStatus.olOutOfOffice).ToList(); if (appointmentItems.Count == 1) { return appointmentItems[0]; // one appointment still left } return appointmentItems[0]; } } }