More Outlook Resource Sites

Microsoft Developer Network (MSDN)

FAQs and other general resources

share code 23-Mar-2017 00:58

Looking for help with Outlook programming projects — VSTO, add-ins, VBA, custom Outlook forms, etc.? You′ve come to the right place!

NEW! >> Subscribe to this site via RSS. For more RSS options, see the complete list of feeds on our main news page.

Code level: advanced    Code area: Outlook and .NET Printer Friendly Version
Title: CommandBar & ExplorerWrapper c# example
Description: Wrapping an Explorer, Create a CommandBar, ComboBox, Button...
Date: 25-Feb-2005  21:30
Code level: advanced
Code area: Outlook and .NET
Posted by: Helmut Obertanner
This message is displayed as VB.NET
 This requested Example uses 3 Files, called XExplorer.cs, ActiveExplorers.cs and Connect.cs
It Creates a New Menubar with a ComboBox with some Values and a Button to create a new Email.
Written in C#.
Create a new Visual Studio c# AddIn for Outlook called XConnect.
Add this files to your Solution
---------------------------------Connect.cs--------------------------------------------------

namespace XConnect
{
	using System;
	using System.Diagnostics ;
	using Microsoft.Office.Core;
	using Extensibility;
	using System.Runtime.InteropServices;
	using Ol = Microsoft.Office.Interop.Outlook ;  
	using MSO = Microsoft.Office.Core;  
	using System.Windows.Forms; 
	

	#region Read me for Add-in installation and setup information.
	// When run, the Add-in wizard prepared the registry for the Add-in.
	// At a later time, if the Add-in becomes unavailable for reasons such as:
	//   1) You moved this project to a computer other than which is was originally created on.
	//   2) You chose 'Yes' when presented with a message asking if you wish to remove the Add-in.
	//   3) Registry corruption.
	// you will need to re-register the Add-in by building the MyAddin21Setup project 
	// by right clicking the project in the Solution Explorer, then choosing install.
	#endregion
	
	/// <summary>
	///   The object for implementing an Add-in.
	/// </summary>
	/// <seealso class='IDTExtensibility2' />
	[GuidAttribute("9B73D13F-0476-4E16-86EF-A3A6B54EFFA8"), ProgId("XConnect.Connect")]
	public class AddIn : Object, Extensibility.IDTExtensibility2
	{

		/// <summary>
		/// The Outlook Application Object
		/// </summary>
		private Ol.Application myApplicationObject;

		/// <summary>
		/// My COM AddIn Instance
		/// </summary>
		private object myAddInInstance;

		/// <summary>
		/// The Explorers Collection
		/// </summary>
		Ol.ExplorersClass myExplorers; 


		/// <summary>
		/// The Explorer Wrapper
		/// </summary>
		ActiveExplorers myActiveExplorers = null;

		/// <summary>
		///		Implements the constructor for the Add-in object.
		///		Place your initialization code within this method.
		/// </summary>
		public AddIn()
		{
		}

		/// <summary>
		///      Implements the OnConnection method of the IDTExtensibility2 interface.
		///      Receives notification that the Add-in is being loaded.
		/// </summary>
		/// <param term='application'>
		///      Root object of the host application.
		/// </param>
		/// <param term='connectMode'>
		///      Describes how the Add-in is being loaded.
		/// </param>
		/// <param term='addInInst'>
		///      Object representing this Add-in.
		/// </param>
		/// <seealso class='IDTExtensibility2' />
		public void OnConnection(object application, Extensibility.ext_ConnectMode connectMode, object addInInst, ref System.Array custom)
		{
			// Get the initial Application object
			myApplicationObject = (Ol.Application) application;
			myAddInInstance = addInInst;

		}

		/// <summary>
		///     Implements the OnDisconnection method of the IDTExtensibility2 interface.
		///     Receives notification that the Add-in is being unloaded.
		/// </summary>
		/// <param term='disconnectMode'>
		///      Describes how the Add-in is being unloaded.
		/// </param>
		/// <param term='custom'>
		///      Array of parameters that are host application specific.
		/// </param>
		/// <seealso class='IDTExtensibility2' />
		public void OnDisconnection(Extensibility.ext_DisconnectMode disconnectMode, ref System.Array custom)
		{
			myActiveExplorers = null;
		
			if (myExplorers != null) Marshal.ReleaseComObject (myExplorers);
			if (myApplicationObject != null) Marshal.ReleaseComObject (myApplicationObject);
			GC.Collect ();
		}

		/// <summary>
		///      Implements the OnAddInsUpdate method of the IDTExtensibility2 interface.
		///      Receives notification that the collection of Add-ins has changed.
		/// </summary>
		/// <param term='custom'>
		///      Array of parameters that are host application specific.
		/// </param>
		/// <seealso class='IDTExtensibility2' />
		public void OnAddInsUpdate(ref System.Array custom)
		{
		}

		/// <summary>
		///      Implements the OnStartupComplete method of the IDTExtensibility2 interface.
		///      Receives notification that the host application has completed loading.
		/// </summary>
		/// <param term='custom'>
		///      Array of parameters that are host application specific.
		/// </param>
		/// <seealso class='IDTExtensibility2' />
		public void OnStartupComplete(ref System.Array custom)
		{
			// Create an instance of Explorer-wrapper
			myActiveExplorers = new ActiveExplorers ();

			// Add the initial Explorer to Collection
			myActiveExplorers.Add (myApplicationObject.ActiveExplorer ());

			// Get the Explorers Collection and register for the Add events
			myExplorers = (Ol.ExplorersClass) myApplicationObject.Explorers; 
			
			// register for the Add events
			myExplorers.NewExplorer +=new Microsoft.Office.Interop.Outlook.ExplorersEvents_NewExplorerEventHandler(myExplorers_NewExplorer);
		
		}

		/// <summary>
		///      Implements the OnBeginShutdown method of the IDTExtensibility2 interface.
		///      Receives notification that the host application is being unloaded.
		/// </summary>
		/// <param term='custom'>
		///      Array of parameters that are host application specific.
		/// </param>
		/// <seealso class='IDTExtensibility2' />
		public void OnBeginShutdown(ref System.Array custom)
		{
		}

		/// <summary>
		/// Handles when a new explorer is opened.
		/// </summary>
		/// <param name="Explorer"></param>
		private void myExplorers_NewExplorer(Microsoft.Office.Interop.Outlook.Explorer Explorer)
		{
			// We add it to our collection
			// Menu will created and handled in XExplorer
			myActiveExplorers.Add (Explorer);
		}
	}
}

--------------------------------------- end of Connect.cs -------------------------------------------------------------------------------------------

--------------------------------------- ActiveExplorers.cs -------------------------------------------------------------------------------------------

using System;
using System.Diagnostics ;
using System.Windows.Forms;  
using Extensibility;
using System.Runtime.InteropServices;
using Ol = Microsoft.Office.Interop.Outlook ;  
using MSO = Microsoft.Office.Core;  

namespace XConnect
{
	/// <summary>
	/// This Class holds a List of Active Explorers
	/// </summary>
	public class ActiveExplorers
	{

		/// <summary>
		/// A Collection of Active Explorers
		/// </summary>
		private System.Collections.SortedList myActiveExplorers = null; 

		#region Construction / Cleanup

		/// <summary>
		/// Constructor
		/// We create our emty list here
		/// </summary>
		public ActiveExplorers()
		{
			try
			{
				// Create the empty list
				// We start with a initial value for 25 Explorers, just enough for a Poweruser, Ha Ha Ha
				myActiveExplorers = new System.Collections.SortedList (25);
			}
			catch (System.Exception ex)
			{
				MessageBox.Show (ex.Message);
			}	
		}

		/// <summary>
		/// Destructor
		/// </summary>
		~ActiveExplorers()
		{	
			try
			{
				myActiveExplorers.Clear ();
				myActiveExplorers = null;				
			}
			catch (System.Exception ex)
			{
				MessageBox.Show (ex.Message);
			}			
		}

		#endregion

		#region Public Functions

		/// <summary>
		/// Adds a new Explorer to our Collection
		/// </summary>
		/// <param name="explorer"></param>
		public void Add(Ol.Explorer explorer)
		{
			try
			{
				// Create an XExplorer here
				XExplorer myExplorer = new XExplorer (explorer);
				
				// Register for Close Event
				myExplorer.Explorer_Closed +=new EventHandler(myExplorer_Explorer_Closed);
				
				// Remember me
				myActiveExplorers.Add (myExplorer.ID, myExplorer);
	
			}
			catch (System.Exception ex)
			{
				MessageBox.Show (ex.Message);
			}		
		}


		#endregion

		#region Eventhandlers
		
		/// <summary>
		/// Eventhandler when Explorer was closed
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void myExplorer_Explorer_Closed(object sender, EventArgs e)
		{
			XExplorer closingExplorer = (XExplorer) sender;
			myActiveExplorers.Remove (closingExplorer.ID);
		}

		#endregion
	}
}

--------------------------------------- end of ActiveExplorers.cs -----------------------------------------------------------------------------------

---------------------------------------- the XExplorer.cs ----------------------------------------------------------------------------------------------

using System;
using System.Diagnostics ;
using System.Windows.Forms;  
using Extensibility;
using System.Runtime.InteropServices;
using Ol = Microsoft.Office.Interop.Outlook ;  
using MSO = Microsoft.Office.Core;  

namespace XConnect
{
	/// <summary>
	/// Zusammenfassung für XExplorer.
	/// </summary>
	public class XExplorer
	{

		#region Events

		/// <summary>
		/// When Outlook Explorer is closed, we send an Event to ActiveExplorers
		/// </summary>
		public event EventHandler Explorer_Closed;
			
		#endregion

		#region Private Variables

		/// <summary>
		/// Object for COM interop
		/// </summary>
		private object myMissing = System.Reflection.Missing.Value ;  

		/// <summary>
		/// The Outlook Explorer to wrapp
		/// </summary>
		private Ol.ExplorerClass myExplorer = null;

		/// <summary>
		/// The Explorer HashCode
		/// </summary>
		private int myID = 0; 

		/// <summary>
		/// The Explorer ComboBox
		/// </summary>
		private MSO.CommandBarComboBox myCombobox = null;


		/// <summary>
		/// The Explorer Email-Button
		/// </summary>
		private MSO.CommandBarButton myButton = null;

		/// <summary>
		/// My CommandBar in Explorer
		/// </summary>
		private MSO.CommandBar myCommandBar = null;

		#endregion

		#region Public Properties

		/// <summary>
		/// The ID of this Explorer
		/// </summary>
		public int ID
		{
			get { return myID; }
			set {}
		}


		#endregion

		/// <summary>
		/// Construction
		/// Remember the Explorer here.
		/// Registers the Clsoe Event.
		/// Setup the Menu for the Explorer here
		/// </summary>
		/// <param name="newExplorer"></param>
		public XExplorer(Ol.Explorer newExplorer)
		{
			// Remember the Explorer
			myExplorer = (Ol.ExplorerClass) newExplorer;

			// Get the Explorer ID
			myID = myExplorer.GetHashCode ();

			// Register for Events
			myExplorer.ExplorerEvents_Event_Close +=new Microsoft.Office.Interop.Outlook.ExplorerEvents_CloseEventHandler(myExplorer_ExplorerEvents_Event_Close);

			// Create my Explorer Menu
			CreateMenu();
		
		}

		/// <summary>
		/// This Handles the Explorer Close Event.
		/// We Inform the ActiveExplorers Collection to remove ourself, so all references would be released
		/// </summary>
		private void myExplorer_ExplorerEvents_Event_Close()
		{
			// Remove eventhadler
			myExplorer.ExplorerEvents_Event_Close -=new Microsoft.Office.Interop.Outlook.ExplorerEvents_CloseEventHandler(myExplorer_ExplorerEvents_Event_Close);
			
			// Inform Active Explorerscollection, that we are closed.
			OnClose();					
		}

		/// <summary>
		/// This Function creates a ComboBox and a Button in the Explorer Menu and registers for the Click Event
		/// </summary>
		private void CreateMenu()
		{
			try
			{
				
				myExplorer.Activate ();
				
				/// Since the CommandBars not always get cleaned, first try to get our commandbar
				/// We could do this with a try / catch, but I always try to avoid exceptions
				/// so loop over the Explorer.Commandbars and have a look for my CommandBar
					foreach ( MSO.CommandBar bar in myExplorer.CommandBars )
					{
						// test for our Name
						if (bar.Name == "XConnect")
						{
							// o.k. we got it - atomic waste...
							bar.Delete ();
							break;
						}
					}
				
				// Start with a fresh one...
				myCommandBar = myExplorer.CommandBars.Add ("XConnect", myMissing, 0, 1); 

				// Add my ComboBox Control
				myCombobox = (MSO.CommandBarComboBox) myCommandBar.Controls.Add (MSO.MsoControlType.msoControlComboBox , myMissing, myMissing, 1, 1);

				myCombobox.Caption = "Company: ";
				myCombobox.Width = 270;

				myCombobox.Style = MSO.MsoComboStyle.msoComboLabel;  
					
				myCombobox.Tag = myID.ToString();

				// Fill the ComboBox
				FillComboFromDB();

				// Add my button
				myButton = (MSO.CommandBarButton) myCommandBar.Controls.Add (MSO.MsoControlType.msoControlButton, myMissing, myMissing, 2, 1);  
				
				myButton.Caption = "XMail";
				myButton.Tag = myID.ToString();
				myButton.Style = MSO.MsoButtonStyle.msoButtonIconAndCaption;
				// Use one off 2 zilliards Office Icons....
				myButton.FaceId = 24;

				// Register for Click event
				myButton.Click += new MSO._CommandBarButtonEvents_ClickEventHandler(myButton_Click);
			
				// Make Menu Visible in TOP of Menus
				myCommandBar.Visible = true;
				myCommandBar.Enabled = true;
				myCommandBar.Position = MSO.MsoBarPosition.msoBarTop;  
			
			}
			catch (System.Exception ex)
			{
				MessageBox.Show (ex.Message);
			}
		}
		
		/// <summary>
		/// This function Fills the ComboBox from DataBase
		/// </summary>
		private void FillComboFromDB()
		{
			/// Simply a Jumpstart, not a complete solution
			/// Solutions costs money ;-)
			try
			{
				myCombobox.Clear ();
				
				// Should come from DB
				myCombobox.AddItem ("Foo",1);
				myCombobox.AddItem ("Bar",2);
				myCombobox.AddItem ("X4U",3);
				myCombobox.AddItem ("Slipstick",4);
				myCombobox.AddItem ("Turtleflock",5);
				myCombobox.AddItem ("DATALOG",6);

			}
			catch (System.Exception ex)
			{
				MessageBox.Show (ex.Message);
			}			
		}
		
		/// <summary>
		/// This function creates a new Email with Data from Combobox in Subject
		/// </summary>
		private void CreateNewMail(string subject)
		{
			Ol.MailItem myNewMail = null;
			try
			{
				// Create a new MailItem
				myNewMail = (Ol.MailItem) myExplorer.Application.CreateItem (Ol.OlItemType.olMailItem );    

				// Assign the Subject
				myNewMail.Subject = subject;

				// Display the Email
				myNewMail.Display (false);

			}
			catch (System.Exception ex)
			{
				MessageBox.Show (ex.Message);
			}
			finally
			{
				if (myNewMail != null)	Marshal.ReleaseComObject (myNewMail);
			}
		}

		/// <summary>
		/// Handles the Email-Button Click Event
		/// </summary>
		/// <param name="Ctrl"></param>
		/// <param name="CancelDefault"></param>
		private void myButton_Click(MSO.CommandBarButton Ctrl, ref bool CancelDefault)
		{
			try
			{
				// See if the Event comes from our Explorer
				if (Ctrl.Tag != myID.ToString ()) return;

				string mySubject = "Learned from Company: " + myCombobox.Text + " @" + DateTime.Now.Hour + ":" + DateTime.Now.Minute ;     		
				CreateNewMail(mySubject);
			}
			catch (System.Exception ex)
			{
				MessageBox.Show (ex.Message);
			}			
		}

		/// <summary>
		/// Raises an event, that explorer is closing 
		/// </summary>
		private void OnClose()
		{

			// Raise event
			OnExplorer_Closed(new EventArgs ());
		
			// Cleanup resources here
			// Unregister Click event
			myButton.Click -= new MSO._CommandBarButtonEvents_ClickEventHandler(myButton_Click);
			
			if ( myButton != null) Marshal.ReleaseComObject (myButton);	
			if ( myCombobox != null) Marshal.ReleaseComObject (myCombobox);	
			if ( myCommandBar != null)
			{
				myCommandBar.Delete ();
				Marshal.ReleaseComObject (myCommandBar);	
			}
			if (myExplorer != null) Marshal.ReleaseComObject (myExplorer);
		}

		/// <summary>
		/// EventHandler for Close event
		/// </summary>
		/// <param name="e"></param>
		protected virtual void OnExplorer_Closed(EventArgs e)
		{
			if (Explorer_Closed != null)
			{
				Explorer_Closed(this, e);
			}
		}

	}
}


---------------------------------------------------- End of XExplorer.cs ---------------------------------------------------------------

Feel free to Test & Modify.
Greetings, Helmut Obertanner
All 89comments
Page [ 1 2 3 4 5 6 7 8 9 Next >>  
  08-Mar-2005  19:44   
I'm getting a "Specfied Class is not valid" exception on this line myExplorers = (Ol.ExplorersClass) myApplicationObject.Explorers; in OnStartupComplete.

Any ideas how this code worked?
  08-Mar-2005  19:45   
I meant to write "Specified Cast is not valid"
  09-Mar-2005  02:47   
Remove reference to Office.dll and ad new reference to COM Office Dll.
The original Reference created with VisualStudion Wizard points to wrong dll.

Greets, Helmut Obertanner
  10-Mar-2005  15:31   
I am also using this example as a guideline with the COM Office 11.0 library and Outlook 2003. I am also getting a similar error. Should I be doing anything different?

Basically I am dealing with a similar issue where my menu events disappear after I open a Windows form. I defined a NewExploere event but I find that it never gets triggered. Now I am trying to test if the close event(taking cues from your example) is getting triggered after the form is called. That is where I have run into the above exception at run time.

Any help you can provide will be greatly appreciated.
Thanks,
Poonam
  11-Mar-2005  02:48   
Hello Mr. Muragi,
Have you also removed the Office DLL from your project references ?

Greets, Helmut Obertanner
  11-Mar-2005  22:56   
Yes I did remove it, but somehow I still could not get it to work. But I have found another solution to the problem:

1) Define an Activate event handler for the Explorer object - this is a definition I got to work after quite a struggle:

Outlook.Explorer oActiveExplorer;

// Cast this correctly - very important - this is required because it has both an event
// and method named Activate

Outlook.ExplorerEvents_10_Event eActiveExplorer = (Outlook.ExplorerEvents_10_Event)oActiveExplorer;

eActiveExplorer.Activate +=new Outlook.ExplorerEvents_10_ActivateEventHandler(onActivateExplorer);

And in method for the event handler:

onActivateExplorer()
{
// Build the menu - in this, if the menu already exists, recreate the event handlers

}

This is all working now - thanks Helmut for your tips.
Poonam
 
  22-Mar-2005  09:17   
Hi,

I have copied all the three files but still i am not able to see any bar.
I have installed the addin.
Please help.

Thanks and regards,
Mohit
  22-Mar-2005  09:21   
Hello mohit,
please change the following in Connect.cs from:
[GuidAttribute("9B73D13F-0476-4E16-86EF-A3A6B54EFFA8"), ProgId("XConnect.AddIn")]
to
[GuidAttribute("9B73D13F-0476-4E16-86EF-A3A6B54EFFA8"), ProgId("XConnect.Connect")]

Greets, Helmut Obertanner
  22-Mar-2005  17:00   
Hi Helmut,

Great!!! it's working fine now.
is there any way to add a context menu item when we right click on the email address in the email (TO CC BCC)list.

Thanks and Regards,
Mohit
  23-Mar-2005  02:12   
Hello Mohit,
haven't done so, so I'm not sure.
But the contaxtmenu is also a CommandBar wich maybe could be identified by it's name.

Greets, Helmut Obertanner
 
Page [ 1 2 3 4 5 6 7 8 9 Next >>