///
/// Copyright © 2003-2008 JetBrains s.r.o.
/// You may distribute under the terms of the GNU General Public License, as published by the Free Software Foundation, version 2 (see License.txt in the repository root folder).
///
using System;
using System.Diagnostics;
using System.IO;
using System.Windows.Forms;
using JetBrains.Omea.Base;
using JetBrains.Omea.Diagnostics;
using System.Runtime.InteropServices;
using System.Reflection;
using JetBrains.Omea.COM;
using JetBrains.Omea.OpenAPI;
using JetBrains.UI.Interop;
using Microsoft.Win32;
namespace JetBrains.Omea.OutlookPlugin
{
internal class OutlookMailDeliver
{
private _com_OutlookExporer _explorer = null;
private System.IntPtr _mainWnd;
private const int cTimeOut = 2000;
protected static Tracer _tracer = new Tracer( "OutlookMailDeliver" );
private static bool _shown = false;
private const string cErrorSendReceiveV11 = "Failed to invoke Send/Receive command. Please make sure that the 'Send/Receive All' menu item is available in the 'Tools | Send/Receive' menu in Outlook.";
private const string cErrorSendReceiveVolder = "Failed to invoke Send/Receive command. Please make sure that the 'Send/Receive' button is available on the main toolbar of Outlook.";
private const string cErrorCOMInitialize = "Omea is unable to initialize Outlook. Most probably your antivirus software prevents it to activate Outlook DLLs. Please contact for support.";
protected void ReleaseCOM()
{
try
{
if ( _explorer != null )
{
_explorer.Release();
}
}
catch ( COMException exception )
{
_tracer.TraceException( exception );
}
}
protected OutlookMailDeliver()
{
_mainWnd = new IntPtr( 0 );
}
public static void DeliverNow()
{
try
{
new OutlookMailDeliver().SendReceive();
}
catch ( COMException exception )
{
_tracer.TraceException( exception );
}
catch ( FileNotFoundException exception )
{
_tracer.TraceException( exception );
}
catch ( InvalidComObjectException exception )
{
_tracer.TraceException( exception );
}
catch ( InvalidCastException exception )
{
_tracer.TraceException( exception );
}
catch ( System.Threading.ThreadAbortException exception )
{
_tracer.TraceException( exception );
}
catch ( Exception exception )
{
Exception innerException = exception.InnerException;
while ( innerException != null )
{
if ( innerException is COMException )
{
_tracer.Trace( "Ignore COM exceptions" );
return;
}
Tracer._TraceException( innerException );
}
Tracer._TraceException( exception );
Core.ReportException( exception, ExceptionReportFlags.AttachLog );
}
}
public void SendReceive()
{
try
{
if ( !OutlookSession.IsOutlookRun )
{
OutlookGUIInit.StartOutlook( ProcessWindowStyle.Minimized );
if ( !IsMainWndReady() ) return;
OutlookGUIInit.ActivateGUI( _mainWnd );
}
_explorer = OutlookGUIInit.IsOutlookExplorerReady( cTimeOut );
if ( _explorer == null )
{
StandartJobs.MessageBox( cErrorCOMInitialize, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error );
return;
}
ProcessDeliverNow( );
ReleaseCOM();
}
catch ( COMException exception )
{
_tracer.TraceException( exception );
}
catch ( FileNotFoundException exception )
{
_tracer.TraceException( exception );
}
catch ( InvalidComObjectException exception )
{
_tracer.TraceException( exception );
}
catch ( InvalidCastException exception )
{
_tracer.TraceException( exception );
}
}
private void ShowErrorMessage()
{
if( !_shown )
{
_shown = true;
string message = (OutlookSession.Version >= 11) ? cErrorSendReceiveV11 : cErrorSendReceiveVolder;
StandartJobs.MessageBox( message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error );
}
}
protected void ProcessDeliverNow( )
{
try
{
/*
_tracer.Trace( "Start of send/receive" );
_tracer.Trace( "Get raw pointer on Outlook.Explorer" );
*/
object oDocument = null;
Outlook.Explorer explorer = ( Outlook.Explorer )_explorer.COM_Pointer;
if ( explorer != null )
{
try
{
// _tracer.Trace( "Try to find CommandBars" );
oDocument = explorer.GetType().InvokeMember( "CommandBars", BindingFlags.GetProperty, null, explorer, null );
}
catch ( COMException )
{
ShowErrorMessage();
return;
}
}
else
{
_tracer.Trace( "Cannot find explorer" );
return;
}
if ( oDocument == null )
{
_tracer.Trace( "Cannot find CommandBars" );
ShowErrorMessage();
return;
}
_tracer.Trace( "OutlookSession.Version = " + OutlookSession.Version );
if ( OutlookSession.Version >= 11 )
{
bool found = false;
try
{
object mainMenu = oDocument.GetType().InvokeMember( "Item", BindingFlags.GetProperty, null, oDocument, new object[] { "Menu Bar" } );
if ( mainMenu != null )
{
object toolsMenu = mainMenu.GetType().InvokeMember( "Controls", BindingFlags.GetProperty, null, mainMenu, new object[] { 5 } );
if ( toolsMenu != null )
{
object sendMenu = toolsMenu.GetType().InvokeMember( "Controls", BindingFlags.GetProperty, null, toolsMenu, new object[] { 1 } );
if ( sendMenu != null )
{
object sendReceiveAll = sendMenu.GetType().InvokeMember( "Controls", BindingFlags.GetProperty, null, sendMenu, new object[] { 1 } );
if ( sendReceiveAll != null )
{
sendReceiveAll.GetType().InvokeMember( "Execute",BindingFlags.InvokeMethod,null,sendReceiveAll, new object[] {} );
found = true;
}
}
}
}
}
catch ( COMException exception )
{
_tracer.TraceException( exception );
}
if ( !found )
{
ShowErrorMessage();
return;
}
/*
Parameters [0] = (int) 13;
Parameters [1] = (int) 32828;
object button = oDocument.GetType().InvokeMember( "FindControl",BindingFlags.InvokeMethod,null,oDocument, Parameters );
object controls = button.GetType().InvokeMember( "Controls", BindingFlags.GetProperty, null, button, new object[] {} );
object control0 = controls.GetType().InvokeMember( "Item", BindingFlags.GetProperty, null, controls, new object[] { 2 } );
control0.GetType().InvokeMember( "Execute",BindingFlags.InvokeMethod,null,button, new object[] {} );
*/
}
else
{
object[] Parameters = new Object[2];
Parameters[0] = 1;
Parameters[1] = 5488;
object button = null;
try
{
button = oDocument.GetType().InvokeMember( "FindControl", BindingFlags.InvokeMethod, null, oDocument, Parameters );
if ( button != null )
{
button.GetType().InvokeMember( "Execute", BindingFlags.InvokeMethod, null, button, new object[] {} );
}
}
catch ( COMException exception )
{
_tracer.TraceException( exception );
button = null;
}
if ( button == null )
{
ShowErrorMessage();
return;
}
}
_tracer.Trace("Start of send/receive");
}
catch ( COMException ex )
{
_tracer.TraceException( ex );
}
}
private bool IsMainWndReady( )
{
_mainWnd = OutlookGUIInit.PrepareMainWndReady( cTimeOut );
return (int)_mainWnd != 0;
}
}
internal class OutlookGUIInit
{
public static bool _isFileNotFoundHappened = false;
private static Tracer _tracer = new Tracer( "OutlookGUIInit" );
private OutlookGUIInit(){}
static public void DebugMessageBox( string message )
{
if ( Settings.DebugMessageBox )
MessageBox.Show( message );
}
static public _com_OutlookExporer IsOutlookExplorerLoaded( )
{
Outlook.Application outlook = null;
Outlook.NameSpace nameSpace = null;
_com_OutlookExporer explorer = null;
_isFileNotFoundHappened = false;
try
{
_tracer.Trace("Looking for explorer");
OutlookGUIInit.DebugMessageBox( "Looking for explorer" );
outlook = new Outlook.ApplicationClass();
_tracer.Trace("Outlook.Application object has been initialized properly.");
nameSpace = outlook.GetNamespace("MAPI");
_tracer.Trace("Outlook.NameSpace object has been initialized properly? - " + (nameSpace != null).ToString());
explorer = new _com_OutlookExporer( outlook.ActiveExplorer() );
_tracer.Trace("_com_OutlookExporer wrapper object has been initialized properly.");
OutlookGUIInit.DebugMessageBox( "Get ActiveExplorer" );
if ( explorer == null )
{
_tracer.Trace("Outlook explorer is not found");
}
else
{
_tracer.Trace("Outlook explorer is found");
}
}
catch ( FileNotFoundException exception )
{
_isFileNotFoundHappened = true;
_tracer.TraceException( exception );
}
catch ( COMException exception )
{
_tracer.TraceException( exception );
}
catch ( InvalidComObjectException exception )
{
_tracer.TraceException( exception );
}
catch ( InvalidCastException exception )
{
_tracer.TraceException( exception );
}
finally
{
COM_Object.Release( outlook );
COM_Object.Release( nameSpace );
}
return explorer;
}
static public _com_OutlookExporer IsOutlookExplorerReady( int cTimeOut )
{
int begin = Environment.TickCount;
_com_OutlookExporer explorer = null;
while ( (explorer = IsOutlookExplorerLoaded( )) == null && ( Environment.TickCount - begin ) < cTimeOut )
{
_tracer.Trace("Waiting for explorer");
}
return explorer;
}
static public bool StartAndInitializeOutlook( )
{
if ( OutlookSession.IsOutlookRun )
{
return true;
}
_com_OutlookExporer explorer = null;
try
{
OutlookGUIInit.StartOutlook( ProcessWindowStyle.Minimized );
IntPtr mainWnd = OutlookGUIInit.PrepareMainWndReady( 2000 );
if ( (int)mainWnd == 0 )
{
return false;
}
ActivateGUI( mainWnd );
return IsOutlookExplorerReady( 2000 ) != null;
}
catch ( COMException exception )
{
Tracer._TraceException( exception );
return false;
}
finally
{
if ( explorer != null )
{
try
{
explorer.Release();
}
catch ( COMException exception )
{
Tracer._TraceException( exception );
}
}
}
}
static public void StartOutlook( ProcessWindowStyle processWindowStyle )
{
DebugMessageBox( "Before start Outlook process" );
Tracer._Trace("Loading outlook...");
string path = RegUtil.GetValue( Registry.LocalMachine, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\OUTLOOK.EXE", "" ) as string;
if ( path == null )
{
path = "Outlook.exe";
}
Tracer._Trace("Trying to start Outlook from path =[" + path + "]" );
Process process = new Process();
process.StartInfo.FileName = path;
process.StartInfo.WindowStyle = processWindowStyle;
process.StartInfo.UseShellExecute = false;
try
{
process.Start();
Tracer._Trace("Outlook from path =[" + path + "] started without exceptions." );
}
catch ( System.Threading.ThreadAbortException ex )
{
Tracer._TraceException( ex );
}
catch ( Exception exception )
{
Tracer._Trace( "StartOutlook -- general exception while starting Outlook process:\n" + exception.Message );
process.StartInfo.UseShellExecute = true;
process.StartInfo.FileName = "Outlook.exe";
process.Start();
}
DebugMessageBox( "Outlook was started" );
}
static public void ActivateGUI( System.IntPtr mainWnd )
{
DebugMessageBox( "before ActivateGUI" );
Tracer._Trace("Activate GUI");
Win32Declarations.SendMessage( mainWnd, Win32Declarations.WM_ACTIVATEAPP, (IntPtr) 1, IntPtr.Zero );
DebugMessageBox( "after WM_ACTIVATEAPP" );
Win32Declarations.SendMessage( mainWnd, Win32Declarations.WM_NCACTIVATE, (IntPtr) 0x200001, IntPtr.Zero );
DebugMessageBox( "after WM_NCACTIVATE" );
Win32Declarations.SendMessage( mainWnd, Win32Declarations.WM_ACTIVATE, (IntPtr) 0x200001, IntPtr.Zero );
DebugMessageBox( "after WM_ACTIVATE" );
Win32Declarations.SendMessage( mainWnd, Win32Declarations.WM_ACTIVATETOPLEVEL, (IntPtr) 0x200001, (IntPtr) 0x13FBE8 );
DebugMessageBox( "after WM_ACTIVATETOPLEVEL" );
Win32Declarations.SendMessage( mainWnd, Win32Declarations.WM_SETFOCUS, IntPtr.Zero, IntPtr.Zero );
int SIZE_MINIMIZED = 1;
Win32Declarations.SendMessage( mainWnd, Win32Declarations.WM_SIZE, (IntPtr)SIZE_MINIMIZED, IntPtr.Zero );
DebugMessageBox( "after WM_SETFOCUS" );
Tracer._Trace("GUI activated");
}
static public System.IntPtr PrepareMainWndReady( int cTimeOut )
{
IntPtr mainWnd = GenericWindow.FindWindow( "rctrl_renwnd32", null );
int begin = Environment.TickCount;
Tracer._Trace("Waiting while main window is loaded");
while ( (int)mainWnd == 0 && ( Environment.TickCount - begin ) < cTimeOut )
{
mainWnd = GenericWindow.FindWindow( "rctrl_renwnd32", null );
}
return mainWnd;
}
}
}