Search code examples
c#outlookvstooutlook-addinoffice-addins

Creating an On-send prompt in Outlook with VSTO and in C#


I have a requirement to intercept the sending of a new email. All I want to do initially is ask the user "Are you sure you want to send?" and then to either proceed with the sending or cancel it depending on their response.

I found this code snippet which looks perfect for my needs but couldn't get it to work in a Win Forms test application either in VB.Net or after trying to convert it to C#. It then occurred to me that the code may only work in a VSTO Add-in (Is this correct?).

So I then used this Walkthrough to create a VSTO Add-in in C# and made sure that it worked as described, which it does (it pumps some text into the Subject and Body of a new message).

I have tried to add the first example which is in VB.Net into the working C# example but I'm a novice and don't know enough about VSTO or C# to see where I'm going wrong.

The code compiles without errors but when run, Outlook takes a long time loading the Add-in and displays a dialogue stating:

An add-in could not be found or loaded

and then:

Could not create an instance of startup object PromptToFile_Plug_in.ThisAddIn in assembly PromptToFile Plug-in, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null.

Where am I going wrong?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.Diagnostics;
using Outlook = Microsoft.Office.Interop.Outlook;
using Office = Microsoft.Office.Core;
using System.Windows.Forms;

namespace PromptToFile_Plug_in
{
    public partial class ThisAddIn
    {
        Outlook.Inspectors inspectors;
        Outlook.Application myOlApp = new Outlook.Application();

        private void ThisAddIn_Startup(object sender, System.EventArgs e)
        {
            inspectors = this.Application.Inspectors;
            inspectors.NewInspector +=
            new Microsoft.Office.Interop.Outlook.InspectorsEvents_NewInspectorEventHandler(Inspectors_NewInspector);
        }

        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)
        {
            Outlook.MailItem mailItem = Inspector.CurrentItem as Outlook.MailItem;
            if (mailItem != null)
            {
                if (mailItem.EntryID == null)
                {
                    mailItem.Subject = "This text was added by using code";
                    mailItem.Body = "This text was added by using code";
                }
            }
        }
        private void Initialize_handler()
        {
            myOlApp = this.Application;
        }
        private void myOlApp_ItemSend(object Item, bool Cancel)
        {
            string prompt;

            // prompt = "Are you sure you want to send " + Item.Subject + "?";
            prompt = "Are you sure you want to send?";

            MessageBox.Show(prompt, "Prompt to File", MessageBoxButtons.OKCancel);
            //if (MessageBox.(prompt, Constants.vbYesNo + Constants.vbQuestion, "Sample") == Constants.vbNo)
            //    Cancel = true;
        }

        #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
    }
}

Solution

  • First of all, there is no need to create a new Outlook Application instance in the add-in class:

    Outlook.Application myOlApp = new Outlook.Application();
    

    Instead, use the Application property available in your add-in class.

    Second, there is no need to keep the following method because it will never be called:

    private void Initialize_handler()
    {
        myOlApp = this.Application;
    }
    

    Unlike VBA, you can't subscribe to the events just declaring the source objects with keywords. Instead, you need to subscribe to the events in the code like you did for the NewInspector event. For example, the following code can be used for handling the ItemSend event in VSTO add-ins:

    private void ThisAddIn_Startup(object sender, System.EventArgs e)
    {
        this.Application.ItemSend += new Microsoft.Office.Interop.Outlook.ApplicationEvents_11_ItemSendEventHandler(Application_ItemSend);
    }
    
    void Application_ItemSend(object Item, ref bool Cancel)
    {
        if (Item is Outlook.MailItem)
        {
            Outlook.MailItem mail = (Outlook.MailItem)Item;
            // your code goes here        
        }
    }
    

    Finally, pay attention to the ref attribute for the Cancel parameter in the event handler signature.