Information and Resources on VSTO 3.0 and outlook development

I had a customer who required information and advice on creating an addin for their environment.

Their requirements were to create a button in the Appointment window which simply launches a web page (used to book a meeting room through an internal web application). The URL for this web page would use the start date of the Appointment, so the add-in has to be able to retrieve this start date before launching the web page.The customer wanted information on how to develop this for Outlook. They wanted to use VS2008 but specifically target for Office 2003 and Office 2007 clients.

Here are the examples, code that were sent to them to assist them.

This aricle would help provide an understanding of how commandbars work in Outlook
201095 OL: How to Use CommandBars in Outlook Solutions
https://support.microsoft.com/default.aspx?scid=kb;EN-US;201095

This article provdes bacgroun dinformation on programmming the Office Environment:
306130 How To Create Office COM Add-Ins by Using VBA and Office Developer
https://support.microsoft.com/default.aspx?scid=kb;EN-US;306130

Article on coding using VSTO with Office

Developing Office Solutions
https://msdn.microsoft.com/en-us/library/bb386279.aspx

Microsoft Visual Studio Tools for the Microsoft Office system (version 3.0)
https://msdn.microsoft.com/en-us/library/d2tx7z6d.aspx

Programming Application-Level Add-Ins
https://msdn.microsoft.com/en-us/library/bb157876.aspx

Walkthrough: Creating Your First Application-Level Add-in for Outlook
https://msdn.microsoft.com/en-us/library/cc668191.aspx

Outlook Object Model Overview
https://msdn.microsoft.com/en-us/library/ms268893.aspx

provided a coded sample for the customer to implement in their environment.
The code below tested on a Windows xp3, Outlook 2003 sp2 with Visual Studio 2008 sp1

The Office PIAs (Primary Interop Assemblies) are required for programmatic to office libraries and need to be installed when targeting for office 2003. This is accomplished by running the Office setup program and choosing .NET programmability support.
Click Start | Control Panel |Choose Microsoft Office Professional Edition 2003 and click ‘change’
- This will start the office setup process
Click Add or remove Features and choose ‘next’
Click the checkbox - choose advanced customization of applications and ensure all the products are selected (at least Outlook), then click ‘next’
You will see Microsoft Office Outlook in the list so expand this
The first entry will be .NET Programmability Support, choose this and popup will appear confirming you wish to ‘Run from My Computer’
Click on update and  the office setup will install the Outlook PIAs

Start your Visual Studio Environment and click new project, the new project dialog will appear
You will see Office and the Visual Studio Installed templates
Choose Outlook 2003 Addin
This will start the project environment.
‘ replace the class with the code below
-

using System;
using System.Reflection;
using System.Windows.Forms;
using Microsoft.Office.Core;
using Microsoft.Office.Interop.Outlook;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Collections.Generic;

namespace Elia.Omr2007
{
    public partial class ThisAddIn
    {
        #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

        private List<object> objectsToRelease = new List<object>();

        private void ThisAddIn_Startup(object sender, EventArgs e)
        {
            try
            {
                Inspectors inspectors = this.Application.Inspectors;
                this.objectsToRelease.Add(inspectors);
                inspectors.NewInspector += new InspectorsEvents_NewInspectorEventHandler(Inspectors_NewInspector);
            }
            catch (System.Exception exc)
            {
                MessageBox.Show(exc.ToString(), "Exception...");
            }
        }

        private void ThisAddIn_Shutdown(object sender, EventArgs e)
        {
            try
            {
                foreach (object objectToRelease in this.objectsToRelease)
                {
                    Release(objectToRelease);
                }
            }
            catch (System.Exception exc)
            {
                MessageBox.Show(exc.ToString(), "Exception...");
            }
        }

        private void Inspectors_NewInspector(Inspector inspector)
        {
            AppointmentItem appointment = null;
            CommandBars inspectorCommandBars = null;
            CommandBar eliaCommandBar = null;
            CommandBarControls eliaCommandBarControls = null;
            CommandBarButton meetingRoomButton = null;
            try
            {
                appointment = inspector.CurrentItem as AppointmentItem;
                if (appointment != null)
                {
                    inspectorCommandBars = inspector.CommandBars;
                    eliaCommandBar = inspectorCommandBars.Add("EliaOMR", 1, false, true /*this makes the command bar temporary, no cleanup needed*/);

                    // Add a button to the command bar and create an event handler.
                    eliaCommandBarControls = eliaCommandBar.Controls;
                    meetingRoomButton = (CommandBarButton)eliaCommandBarControls.Add(1, Missing.Value, Missing.Value, Missing.Value, Missing.Value);
                    meetingRoomButton.Style = MsoButtonStyle.msoButtonCaption;
                    meetingRoomButton.Caption = "Meeting Rooms Reservation...";
                    meetingRoomButton.Click += delegate(CommandBarButton ctrl, ref bool cancel)
                    {
                        DateTime startTime = appointment.Start;
                        string url = string.Format("https://meetingrooms.elink.elia.be/site/RedirectFromOutlook.asp?newdate={0}&screenres=640", startTime.ToShortDateString());
                        Process.Start(url);
                    };
                    this.objectsToRelease.Add(appointment);
                    this.objectsToRelease.Add(meetingRoomButton);

                    eliaCommandBar.Visible = true;
                }
            }
            catch (System.Exception exc)
            {
                MessageBox.Show(exc.ToString(), "Exception...");
            }
            finally
            {
                Release(inspectorCommandBars);
                Release(eliaCommandBar);
                Release(eliaCommandBarControls);
            }
        }

        private static void Release(object value)
        {
            if (value != null)
            {
                Marshal.ReleaseComObject(value);
            }
        }
    }
}

It is crucial that calls are made to Marshal.ReleaseComObject; without them all sorts of random errors can apparently occur. So best include cleanup code in any COM interop stuff you develop. here is a explanation for that:
Outlook Item leaks
https://blogs.msdn.com/mstehle/archive/2007/12/07/oom-net-part-2-outlook-item-leaks.aspx

Customer also wanted to know that after all this,what solutions we had for deploying their addins to their clients. Here is a bunck of links provided to help customers with deployment and a tool that you could use to help diagnose potential client side issues.

Reference:
Introduction to Interoperability Between COM and .NET
https://msdn.microsoft.com/en-us/library/bb610378.aspx

Deploying Office Solutions
https://msdn.microsoft.com/en-us/library/bb386179.aspx

Troubleshooting Office Solution Deployment (2003 System)
https://msdn.microsoft.com/en-us/library/bb772071.aspx

Microsoft Visual Studio 2005 Tools for Microsoft Office System: Microsoft PSS VSTO 2005 Client TroubleShooter
https://www.microsoft.com/downloads/details.aspx?familyid=c9fb6a54-8069-4918-a6f9-e744928dfac3&displaylang=en