Home > OS >  How to: Programmatically determine the current Outlook item for new event handler
How to: Programmatically determine the current Outlook item for new event handler

Time:10-22

As the subject suggests, I am trying to determine if an Outlook item is a meeting request, while creating a new .ItemSend event handler. I have looked at ways of doing this with inspector and explorer.

I have reviewed this:

https://learn.microsoft.com/en-us/visualstudio/vsto/how-to-programmatically-determine-the-current-outlook-item?view=vs-2022&tabs=csharp

and this:

ActiveExplorer().Selection returns previously selected mail in Outlook C#

as well as a few of the 'similar questions'.

I have been successful with establishing a new inspector event handler as well as defining the event handler for Application.ItemSend and those are working great. But only when I send meeting requests. Regular emails respond to the event triggers, but restart Outlook, saving an email as a draft, without sending.

I am not sure of combining the use of inspector and explorer to prevent crashing Outlook? I am not sure if I can do this by only using inspector? By only using explorer?

I believe that if I can wrap all of this code with identification of an outlook item as a MailItem or a Meeting Request, I can get around this problem I am having with emails and the new event handler.

A point in the right direction is appreciated. Thanks - - chris

    public partial class ThisAddIn
    {
        private Outlook.Inspectors inspectors = null;
        private Outlook.UserProperty objUserPropertyEventId = null;

        private void ThisAddIn_Startup(object sender, System.EventArgs e)
        {
            inspectors = this.Application.Inspectors;
            inspectors.NewInspector  = new Microsoft.Office.Interop.Outlook.InspectorsEvents_NewInspectorEventHandler(Inspectors_NewInspector);
            // define event handler for ItemSend
            Application.ItemSend  = new Outlook.ApplicationEvents_11_ItemSendEventHandler(Application_ItemSend);
        }

        private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
        {
            // Note:      Outlook no longer raises this event. If you have code that 
            //              must run when Outlook shuts down, see https://go.microsoft.com/fwlink/?LinkId=506785
        }

        void Inspectors_NewInspector(Microsoft.Office.Interop.Outlook.Inspector Inspector)
        {
            // <testing this>
            Outlook.Selection sel = Application.ActiveExplorer().Selection;

            if (sel.Count == 1)
                MessageBox.Show("One selected");

            //Outlook.MailItem mail = sel[1] as Outlook.MailItem;
            Object selObject = this.Application.ActiveExplorer().Selection[1];

            //if (mail != null)
            if (selObject is Outlook.MailItem)
                MessageBox.Show("This is a mail item."/*\n\n"   mail.Subject*/);
            else
                MessageBox.Show("This is NOT a mail item."/*\n\n"   mail.Subject*/);
            // </testing this>

            // <this works, but not for email.  Only meeting requests.>
            #pragma warning disable IDE0019 // Use pattern matching
            Outlook.AppointmentItem appt = Inspector.CurrentItem as Outlook.AppointmentItem;
            #pragma warning restore IDE0019 // Use pattern matching

            // is it an AppointmentItem
            if (appt != null)
            {
                MessageBox.Show("appt != null");
                // is it a meeting request
                if (appt.MeetingStatus == Outlook.OlMeetingStatus.olMeeting)
                {
                    // force time of initial meeting dialog to be 11:29pm
                    // to avoid immediate reminder of upcoming meeting
                    DateTime datDateTime = DateTime.Now;
                    
                    string strYear = datDateTime.ToString().Substring(6, 4);
                    int intYear;
                    intYear = Int32.Parse(strYear);

                    string strMonth = datDateTime.ToString("MM/dd/yyyy").Substring(0, 2);
                    int intMonth;
                    intMonth = Int32.Parse(strMonth);

                    string strDay = datDateTime.ToString("MM/dd/yyyy").Substring(3, 2);
                    int intDay;
                    intDay = Int32.Parse(strDay);

                    string strReqAtt = appt.RequiredAttendees;
                    if (string.IsNullOrEmpty(strReqAtt))
                        appt.Start = new DateTime(intYear, intMonth, intDay, 23, 29, 00);

                    // save to generate EntryId for future reference
                    appt.Save();

                    // save EntryId as UserProperty
                    Outlook.AppointmentItem mtg;
                    mtg = (Outlook.AppointmentItem)Inspector.CurrentItem;

                    if (mtg != null)
                    {
                        if (mtg is Outlook.AppointmentItem)
                        {
                            mtg.MeetingStatus = Outlook.OlMeetingStatus.olMeeting;
                            string strEntryId = mtg.EntryID;

                            Outlook.UserProperties objUserProperties = mtg.UserProperties;
                            objUserPropertyEventId = objUserProperties.Add("MeetingEntryId", Outlook.OlUserPropertyType.olText, true, 1);
                            objUserPropertyEventId.Value = strEntryId;
                        }
                    }
                    if (mtg != null)
                        Marshal.ReleaseComObject(mtg);
                }
                if (appt != null)
                    Marshal.ReleaseComObject(appt);
            }
        }

        public void Application_ItemSend(object Item, ref bool Cancel)
        {
            // use EventId to identify current meeting request
            var app = new Microsoft.Office.Interop.Outlook.Application();
            var ns = app.Session;

            Outlook.AppointmentItem meeting = ns.GetItemFromID(objUserPropertyEventId.Value);
            MessageBox.Show(meeting.Subject);
            //if (meeting.MeetingStatus != Outlook.OlMeetingStatus.olNonMeeting)
            if (meeting.MeetingStatus == Outlook.OlMeetingStatus.olMeeting)
            {
                // is ItemSend a request or a cancel
                if (meeting.MeetingStatus != Outlook.OlMeetingStatus.olMeetingCanceled)
                {
                    MessageBox.Show("MeetingStatus != olMeetingCanceled");
                    Outlook.Recipient recipConf = null;
                    try
                    {
                        // ItemSend is a request
                        if (meeting is Outlook.AppointmentItem)
                        {
                            //if (meeting.MeetingStatus == Outlook.OlMeetingStatus.olMeeting)
                            {
                                Outlook.Recipient recipRoomUser;
                                // if a location was provided
                                if (meeting.Location != null)
                                {
                                    string strLocation = meeting.Location;
                                    bool blnTorF = false;
                                    string strConference = "|";

                                    // Clears lazy room number typing
                                    // Location resource:
                                    // places meeting on 'JHP Conference ###' calendar
                                    // and
                                    // sends email to conference room user with link for Teams meeting
                                    //      conference room user is added to 'Location' by including email in 'Required'
                                    if (!strLocation.Contains("Room - Conference"))
                                        meeting.Location = "";

                                    // Add calendar users (based on room location) to email
                                    // sends email to conference room user with link for Teams meeting
                                    //      conference room user is added to previously cleared 'Location'
                                    //      by including email in 'Required'
                                    if (strLocation.Contains("142"))
                                    {
                                        recipRoomUser = meeting.Recipients.Add("[email protected]");
                                        recipRoomUser = meeting.Recipients.Add("[email protected]");
                                        recipRoomUser.Type = (int)Outlook.OlMeetingRecipientType.olRequired;
                                        if(meeting.Location == "")
                                            meeting.Location = "[email protected]";
                                    }
                                    if (strLocation.Contains("150"))
                                    {
                                        recipRoomUser = meeting.Recipients.Add("[email protected]");
                                        recipRoomUser = meeting.Recipients.Add("[email protected]");
                                        recipRoomUser.Type = (int)Outlook.OlMeetingRecipientType.olRequired;
                                        if (meeting.Location == "")
                                            meeting.Location = "[email protected]";
                                    }
                                    if (strLocation.Contains("242"))
                                    {
                                        recipRoomUser = meeting.Recipients.Add("[email protected]");
                                        recipRoomUser = meeting.Recipients.Add("[email protected]");
                                        recipRoomUser.Type = (int)Outlook.OlMeetingRecipientType.olRequired;
                                        if (meeting.Location == "")
                                            meeting.Location = "[email protected]";
                                    }
                                    if (strLocation.Contains("248"))
                                    {
                                        recipRoomUser = meeting.Recipients.Add("[email protected]");
                                        recipRoomUser = meeting.Recipients.Add("[email protected]");
                                        recipRoomUser.Type = (int)Outlook.OlMeetingRecipientType.olRequired;
                                        if (meeting.Location == "")
                                            meeting.Location = "[email protected]";
                                    }
                                    MessageBox.Show("Location assigned");

                                    // build string of recipients for .Split('|') to array
                                    foreach (Outlook.Recipient objUser in meeting.Recipients)
                                    {
                                        // remove previous location prior to room change
                                        if (!objUser.Name.Contains("JHP Conference") && !objUser.Name.Contains("Room - Conference"))
                                            if (!strConference.Contains(objUser.Name)) // no duplicates
                                                strConference = strConference   objUser.Name   "|";
                                    }

                                    if (strConference != "|")
                                    {
                                        // create array from string without duplicates
                                        //MessageBox.Show("strConference != |\n\n"   strConference);
                                        string[] arrConference = null;
                                        strConference = strConference.TrimStart('|');
                                        arrConference = strConference.Split('|');

                                        // verify array contents
                                        string strCheck = "";
                                        string strReqdAtts = "";
                                        for (int i = 0; i < arrConference.Length - 1; i  )
                                        {
                                            strCheck = strCheck   arrConference[i]   "\n";
                                            strReqdAtts = strReqdAtts   ";"   arrConference[i];
                                        }

                                        //MessageBox.Show("Array contents\n\n"   strCheck);
                                        strReqdAtts = strReqdAtts.TrimStart(';');
                                        //MessageBox.Show("RequiredAttendees contents\n\n"   strReqdAtts);
                                        meeting.RequiredAttendees = strReqdAtts;
                                        //MessageBox.Show(".Add");
                                    }
                                    MessageBox.Show("Attendees assigned");


                                    Cancel = true;
                                    // has the user included "JHP - Room Reservations" for placement
                                    // on the shared calendar for all conference room availability
                                    foreach (Outlook.Recipient objUser in meeting.Recipients)
                                    {
                                        if (objUser.Name == "JHP - Room Reservations")
                                            blnTorF = true;
                                    }
                                    // add "JHP - Room Reservations" if not already included
                                    if (blnTorF == false)
                                    {
                                        recipConf = meeting.Recipients.Add("JHP - Room Reservations");
                                        recipConf.Type = (int)Outlook.OlMeetingRecipientType.olRequired;
                                    }
                                    // resolve recipients
                                    meeting.Recipients.ResolveAll();
                                    meeting.Send();
                                }
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message, "Calendar recipients were not added.");
                    }
                    finally
                    {
                        if (recipConf != null) Marshal.ReleaseComObject(recipConf);
                    }
                }
                else
                //{
                    // ItemSend is a cancel
                    MessageBox.Show("Meeting is cancelled.");
                //}
            }
            else
            {
                MessageBox.Show("Not a meeting");
            }
        }

        #region VSTO generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InternalStartup()
        {
            this.Startup  = new System.EventHandler(ThisAddIn_Startup);
            this.Shutdown  = new System.EventHandler(ThisAddIn_Shutdown);
        }
        #endregion
    }

CodePudding user response:

AppointmentItem is never sent, and hence is never passed to the Application.ItemSend event. What you get is the MeetingItem object. If you need the parent appointment, call MeetingItem.GetAssociatedAppointment.

CodePudding user response:

There is no need to use the Explorer window when the NewInspector event is fired:

 void Inspectors_NewInspector(Microsoft.Office.Interop.Outlook.Inspector Inspector)
        {
            // <testing this>
            Outlook.Selection sel = Application.ActiveExplorer().Selection;

Use the Inspector instance passed as a parameter to the event handler instead.

Also I've noticed the following code in the ItemSend event handler:

 public void Application_ItemSend(object Item, ref bool Cancel)
        {
            // use EventId to identify current meeting request
            var app = new Microsoft.Office.Interop.Outlook.Application();
            var ns = app.Session;

There is no need to create a new Outlook Application instance each time the event is fired. Use the Application property of your add-in class instead (available in the ThisAddIn class).

Also you need to use the Item object passed as a parameter to the ItemSend event handler, so instead of using the following code:

Outlook.AppointmentItem meeting = ns.GetItemFromID(objUserPropertyEventId.Value);
            MessageBox.Show(meeting.Subject);

Check whether an object is of a specific type:

if (Item is Outlook.MeetingItem)

You may try to cast the Item object to a specific type and then check for null:

var obj = Item as Outlook.MeetingItem;
if (obj != null)
{
  'do your work here
}
  • Related