Click here to Skip to main content
15,884,298 members
Articles / Programming Languages / Visual Basic

RSS Feed Aggregator and Blogging Smart Client

Rate me:
Please Sign up or sign in to vote.
4.91/5 (85 votes)
16 Aug 2005CPOL52 min read 1.1M   2.4K   397  
RSS Feed aggregator and blogging Smart Client which uses Enterprise Library, Updater Application Block, lots of XML hacks and desktop tricks. A comprehensive guide to real life hurdles of Smart Client development.
// Copyright � 2005 by Omar Al Zabir. All rights are reserved.
// 
// If you like this code then feel free to go ahead and use it.
// The only thing I ask is that you don't remove or alter my copyright notice.
//
// Your use of this software is entirely at your own risk. I make no claims or
// warrantees about the reliability or fitness of this code for any particular purpose.
// If you make changes or additions to this code please mark your code as being yours.
// 
// website http://www.oazabir.com, email OmarAlZabir@gmail.com, msn oazabir@hotmail.com

using System;
using System.Reflection;
using System.Runtime.InteropServices;

using System.Xml;

namespace RSSCommon.Helper
{
	/// <summary>
	/// Summary description for OutlookHelper.
	/// </summary>
	public class OutlookHelper
	{
		public static object GetObject( string typeName )
		{
			Type objectType = Type.GetTypeFromProgID(typeName);
			return Activator.CreateInstance( objectType );			
		}

		public static object GetProperty( object obj, string propertyName )
		{
			return obj.GetType().InvokeMember( propertyName,
				BindingFlags.GetProperty, null, obj, null );
		}

		public static object GetProperty( object obj, string propertyName, object defaultValue )
		{
			try
			{
				return obj.GetType().InvokeMember( propertyName,
					BindingFlags.GetProperty, null, obj, null );
			}
			catch
			{
				return defaultValue;
			}
		}

		public static object GetItem( object obj, int index )
		{
			object [] parameters = new Object[1];
			parameters[0] = index;
			return obj.GetType().InvokeMember( "Item",
				BindingFlags.GetProperty, null, obj, parameters );
		}
		public static object GetItem( object obj, string name )
		{
			object [] parameters = new Object[1];
			parameters[0] = name;
			return obj.GetType().InvokeMember( "Item",
				BindingFlags.GetProperty, null, obj, parameters );
		}
		public static object SetProperty( object obj, string propertyName, object value )
		{
			object [] parameters = new Object[1];
			parameters[0] = value;
			return obj.GetType().InvokeMember( propertyName, BindingFlags.SetProperty,
				null, obj, parameters );
		}

		public static object CallMethod( object obj, string methodName, params object [] parameters )
		{
			return obj.GetType().InvokeMember( methodName, BindingFlags.InvokeMethod, null, obj,
				parameters );
		}

		public static void StartOutlook( ref object app, ref object name )
		{
			try
			{
				// Try to get existing outlook instance
				app = Marshal.GetActiveObject("Outlook.Application");
				name = GetProperty( app, "Session" );
			}
			catch
			{
				// Create new instance of outlook
				app = GetObject("Outlook.Application");
				name = GetProperty( app, "Session" );
			}
		}

		public static bool EnsureExplorer( object app, object name )
		{
			// Outlook normally remains invisible when new instance created, let's show it minimized
			bool isOutlookInvisible = false;

			object explorer = CallMethod( app, "ActiveExplorer" );
			object explorers = GetProperty( app, "Explorers" );
				
			if( null == explorer )
			{
				isOutlookInvisible = true;

				// Outlook was not open, we are not loading the first outlook. So,
				// let's take some precaution

				object inbox = CallMethod( name, "GetDefaultFolder", 6 ); //OlDefaultFolders.olFolderInbox = 6

				explorer = CallMethod( explorers, "Add", inbox, 1 ); //Outlook.OlWindowState.olMinimized = 1

				Marshal.ReleaseComObject( inbox );
				inbox = null;
			}

			// Force outlook to show its face
			CallMethod( explorer, "Display" );
			SetProperty( explorer, "WindowState", 1 );
			//CallMethod( explorer, "Activate" );
			
			Marshal.ReleaseComObject( explorer );
			explorer = null;

			Marshal.ReleaseComObject( explorers );
			explorers = null;

			return isOutlookInvisible;
		}

		public static void CloseOutlook( object app )
		{
			// Get explorers and close each of them
			object explorer = null;
				
			while( (explorer = CallMethod( app, "ActiveExplorer" )) != null )
			{
				CallMethod( explorer, "Close" );

				Marshal.ReleaseComObject( explorer );
			}			
			
			// shut down outlook
			CallMethod( app, "Quit" );
		}

		public static string SelectFolderPath()
		{
			// Show outlook folder picker
			object app = null, name = null;

			StartOutlook( ref app, ref name );

			// Ensure at least one explorer is visible otherwise we cannot show the folder
			// picker
			bool isOutlookInvisible = EnsureExplorer( app, name );
			
			object folder = CallMethod( name, "PickFolder" );

			string path = null;
			// Get the selected folder name
			if( null != folder )
				path = GetProperty( folder, "FolderPath" ) as string;
			
			if( null != folder )
				Marshal.ReleaseComObject( folder );
			folder = null;

			Marshal.ReleaseComObject( name );
			name = null;

			if( isOutlookInvisible )
				CloseOutlook(app);

			Marshal.ReleaseComObject( app );			
			app = null;			

			// Outlook still hangs around in the task manager until we call this
			GC.Collect();

			return path;
		}

		/*
		public static MAPIFolder GetFolderFromPath( string path )
		{
			Outlook.Application app = new Outlook.ApplicationClass();
			Outlook.NameSpace name = app.Session;

			path = path.TrimStart('\\');
			string [] folders = path.Split('\\');

			Outlook.MAPIFolder mapiFolder = name.Folders[ folders[0] ];
			
			// See if the folder has been renamed
			if( null == mapiFolder )
				return null;
			for( int i = 1; i < folders.Length; i ++ )
			{
				string folderName = folders[i];

				try
				{
					mapiFolder = mapiFolder.Folders[ folderName ];
				}
				catch( System.Exception x )
				{
					mapiFolder = null;
				}

				// The folder may have been renamed
				if( null == mapiFolder )
					return null;
			}

			return mapiFolder;
		}
		*/

		public static object EnsureFolderPath( object name, string path )
		{
			path = path.TrimStart('\\');
			string [] folders = path.Split('\\');

			// See if the first folder in the path exists
			object rootFolders = GetProperty( name, "Folders" );
			object mapiFolder = null;
			try
			{
				 mapiFolder = GetItem( rootFolders, folders[0] );
			}
			catch( Exception x )
			{
				throw new ApplicationException("Base folder not defined properly. Go to 'Options' and select Outlook Base Folder", x );
			}
			
			Marshal.ReleaseComObject( rootFolders );

			// The first folder does not exist, may be the personal folder was closed or deleted,
			// We can abort safely.
			if( null == mapiFolder )
				return null;

			for( int i = 1; i < folders.Length; i ++ )
			{
				string folderName = folders[i];

				object mapiFolders = GetProperty( mapiFolder, "Folders" );

				// See if the child folder exists
				object childFolder = null;
				try
				{
					childFolder = GetItem( mapiFolders, folderName );
				}
				catch {}

				// The folder may have been renamed or deleted
				if( null == childFolder )
				{
					// Create a new folder using the name
					childFolder = CallMethod( mapiFolders, "Add", folderName, Missing.Value );									
				}

				mapiFolder = childFolder;

				// Release the child folders collection
				Marshal.ReleaseComObject( mapiFolders );
				mapiFolders = null;
			}

			// Return the last created folder
			return mapiFolder;
		}

		/// <summary>
		/// Ensures whether we have the proper view for the specified folder
		/// </summary>
		/// <param name="folder"></param>
		public static void EnsureView( object folder, string viewXmlPath )
		{
			if( !System.IO.File.Exists( viewXmlPath ) ) return;
			// 1. Load the view xml file to find out the view name. We must not create duplicate view with 
			// same name
			XmlDocument doc = new XmlDocument();
			doc.Load( viewXmlPath );

			XmlElement viewNameElement = (XmlElement)doc.DocumentElement.SelectSingleNode("viewname");
			string viewName = viewNameElement.InnerText.Trim();

			// 2. Check if this view has already been created
			object views = GetProperty( folder, "Views" );

			object existingView = GetItem( views, viewName );

			// 3. If the view already exist, apply it, otherwise create it
			if( null != existingView )
			{
				// Apply the existing view
				CallMethod( existingView, "Apply" );

				// It has already been created, so let's skip
				Marshal.ReleaseComObject( existingView );
			}
			else
			{
				// Create the new view
				object newView = CallMethod( views, "Add", viewName, 0, 2 );						
				// Outlook.OlViewType.olTableView = 0
				// Outlook.OlViewSaveOption.olViewSaveOptionAllFoldersOfType = 2

				SetProperty( newView, "XML", doc.OuterXml );
				
				CallMethod( newView, "Save" );
				CallMethod( newView, "Apply" );
			}
			
		}

	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect BT, UK (ex British Telecom)
United Kingdom United Kingdom

Comments and Discussions