EB78

Hi All,

I have Outtlook Addin (C# 2.0, VSTO 2005, Outlook 2003),

i subscribed to close event:

explorerEvents.Close += new Outlook.ExplorerEvents_10_CloseEventHandler(OnExplorerClose);

but i never get there, why

Only if i open another explorer (right click on folder--> Open in new folder), and close it , then i get the close

event fired, but when i have only one explorer (main explorer) it's seem to be never fired.

P.S. I also susbscribe to FolderSwitch and SelectionChange explorer events , they works fine.

Any suggestions



Re: Visual Studio Tools for Office Outlook Explorer Close event

Helmut Obertanner

Hello EB87,

this is maybe because you keep a reference to an explorer object or an inspector object and then it will never close.

If you want, have a look at my sample OutlookAdminTools, wich is a C# sample AddIn - but for Office 2007 and VSTOSE.

If you remove the references and the 2007 specific code it should work also for Ol2003.

Here you can see that you will get the Explorer Close event also for a single explorer.

http://www.x4u.de/Outlook/Codesnippets/tabid/61/Default.aspx

Hope this helps,

greets, Helmut






Re: Visual Studio Tools for Office Outlook Explorer Close event

EB78

Thanks for response,

Greate samples http://www.x4u.de/Outlook/Codesnippets/tabid/61/Default.aspx

this is more or less how i implemented the work with explorers.

>this is maybe because you keep a reference to an explorer object or an inspector object and then it will never close.

What do you mean by sayin "then it will never close"

Also i checked and even when i start Outlook ( with one explorer ) and my AddIn is loaded, after short period of time

when i see in my log file that AddIn loaded and everythin registered, i close the outlook , and close event not fired.

(I didn't open any inspector).

I don't know what i doing wrong.

TNX





Re: Visual Studio Tools for Office Outlook Explorer Close event

Misha Shneerson - MSFT

I think you are not getting the event because VSTO 2005 for Outlook tracks number of active Outlook windows and unloads your add-in when last explorer/inspector is closed.
I believe Andrew Whitechapel has an entire VSTO 2005 for Outlook architecture article published.

Here is his blog entry that talks about it - http://blogs.officezealot.com/whitechapel/archive/2005/07/10/6747.aspx

And here is the complete architecture article http://msdn2.microsoft.com/en-us/library/aa537182(office.11).aspx#office_vstooutlookadd-inarchitecture_problemswithoutlook






Re: Visual Studio Tools for Office Outlook Explorer Close event

EB78

Thanks for replay,

I created new Outlook AddIn and just subscribed to explorer's FodlerSwitch and Close.

I launch the Outlook, and without open any window when outlook is opened i click the 'x' (close outlook).

The CLOSE never fired (FolderSwitch works properly).

Anu ideas





Re: Visual Studio Tools for Office Outlook Explorer Close event

Helmut Obertanner

Hello,

can you post how your startup code looks like

However, in my sample I will get the close event.

I will also try to write a small sample from scratch.

"Never get a close event" -> When you have a reference to your COM object somewhere in your code,

you won't get the close event, because the explorer doesn't close because the COM ref counter says it's still in use and therefore you won't get the close event.

And this is why there is a tool like vsto - it makes sure that when the AddIn is unloaded, it makes sure that all references to COM objects are released to prevent memoryleaks and application remaining in memory.

So - I will give it a try.

Greets, Helmut






Re: Visual Studio Tools for Office Outlook Explorer Close event

EB78

Thanks Helmut,

The code snippet:

........................

..........................

Outlook.ExplorerClass expl;

private void ThisApplication_Startup(object sender, System.EventArgs e)

{

expl = this.ActiveExplorer() as Outlook.ExplorerClass;

expl.ExplorerEvents_10_Event_Close += new Microsoft.Office.Interop.Outlook.ExplorerEvents_10_CloseEventHandler(expl_ExplorerEvents_10_Event_Close);

}

void expl_ExplorerEvents_10_Event_Close()

{

MessageBox.Show("Explorer Close!");

}

That's all,

Thanks





Re: Visual Studio Tools for Office Outlook Explorer Close event

Helmut Obertanner

Hi,

I crosschecked and put some snippets from my sample OutlookAdminTools together.

Just create a new Outlook AddIn named ExplorerTest and paste in the complete code below.

Set a breakpoint to UnwrapExplorer and try.

You will see that also if you have only the first explorer, even multiple explorers - you will get the close event everytime.

Hope this helps,

greets, Helmut

------------------------------------------------------------------------------------------------------------

Code Snippet

using System;

using System.Windows.Forms;

using Microsoft.VisualStudio.Tools.Applications.Runtime;

using Outlook = Microsoft.Office.Interop.Outlook;

using Office = Microsoft.Office.Core;

using System.Collections;

using System.Diagnostics;

using System.Reflection;

namespace ExplorerTest

{

public partial class ThisAddIn

{

/// <summary>

/// This generic collection holds a reference to our open explorers.

/// </summary>

Hashtable _WrappedExplorers;

/// <summary>

/// This variable must be used to keep a reference to the Application Explorers collection.

/// Required to get informed about new Explorers.

/// </summary>

Outlook.Explorers _Explorers;

private void ThisAddIn_Startup(object sender, System.EventArgs e)

{

// initialize the List that will keep an eye on our active Outlook Explorers.

_WrappedExplorers = new Hashtable(10);

// Do we have already some explorers after startup

_Explorers = Application.Explorers;

for (int i = _Explorers.Count; i >= 1; i--)

{

// Wrap the Explorer and do some usefull with it

WrapExplorer(_Explorers[i]);

}

// remember the Outlook.Explorers (GC)

_Explorers = this.Application.Explorers;

// register for new Explorer event.

_Explorers.NewExplorer += new Outlook.ExplorersEvents_NewExplorerEventHandler(Explorers_NewExplorer);

}

private void ThisAddIn_Shutdown(object sender, System.EventArgs e)

{

// remove all references to the wrapped explorers.

_WrappedExplorers.Clear();

_Explorers = null;

}

/// <summary>

/// This event occures en a new outlook explorer has been opened.

/// </summary>

/// <param name="Explorer">The opened Outlook Explorer object.</param>

void Explorers_NewExplorer(Outlook.Explorer Explorer)

{

// Wrap the Explorer and do some usefull with it

Outlook.Explorer activeExplorer = Application.ActiveExplorer();

WrapExplorer(activeExplorer);

}

/// <summary>

/// This method wraps an Outlook Explorer object and registers for the ExplorerClosed event.

/// </summary>

/// <param name="Explorer">The Outlook Explorer Object.</param>

void WrapExplorer(Outlook.Explorer Explorer)

{

// Wrap the Explorer and do some usefull with it

ExplorerWrapper wrappedExplorer = new ExplorerWrapper(Explorer);

// register for the closed event, so we can releas it from memory

wrappedExplorer.ExplorerClosed += new ExplorerClosedDelegate(UnwrapExplorer);

_WrappedExplorers.Add(wrappedExplorer.ID, wrappedExplorer);

}

/// <summary>

/// This method should be called when a wrapped Outlook Explorer has been closed.

/// </summary>

/// <param name="explorerId">The unique ID of the closed explorer.</param>

void UnwrapExplorer(Guid explorerId)

{

// if we have a reference to this explorer we can release it now

if (_WrappedExplorers.ContainsKey(explorerId))

{

_WrappedExplorers.Remove(explorerId);

}

}

#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

}

#region delegates used handling explorers

/// <summary>

/// A delegate used to inform the application that an explorer has been closed.

/// </summary>

/// <param name="explorerId">The unique ID of the Explorer that has been closed.</param>

internal delegate void ExplorerClosedDelegate(Guid explorerId);

#endregion

#region ExplorerWrapper

/// <summary>

/// The ExplorerWrapper is used to wrap around an Outlook Explorer.

/// It keeps a reference to the Explorer in memory and registers for the Explorer events.

/// </summary>

internal class ExplorerWrapper

{

#region explorer wrapper events

/// <summary>

/// This event is fired from out wrapper when the wrapped Outlook Explorer has been closed.

/// </summary>

public event ExplorerClosedDelegate ExplorerClosed;

#endregion

#region explorer wrapper variables & properties

/// <summary>

/// An unique ID that can used to identify this explorer (commandbars, buttons, etc...)

/// </summary>

Guid _Id;

/// <summary>

/// An unique ID that can used to identify this explorer (commandbars, buttons, etc...)

/// </summary>

public Guid ID

{

get { return _Id; }

}

/// <summary>

/// The Outlook Explorer object used to keep a reference in memory and register for the explorer events.

/// </summary>

Outlook.ExplorerClass _Explorer;

/// <summary>

/// The Outlook Explorer object used to keep a reference in memory and register for the explorer events.

/// </summary>

public Outlook.Explorer Explorer

{

get { return _Explorer; }

}

/// <summary>

/// A Missing.Value used for COM interoperability.

/// </summary>

object _Missing = System.Reflection.Missing.Value;

#endregion

#region explorer wrapper construction and cleanup

/// <summary>

/// The construction code.

/// </summary>

/// <param name="explorer">The outlook explorer that should be wrapped.</param>

public ExplorerWrapper(Outlook.Explorer explorer)

{

try

{

_Id = Guid.NewGuid();

_Explorer = explorer as Outlook.ExplorerClass;

if (_Explorer != null)

{

_Explorer.FolderSwitch += new Microsoft.Office.Interop.Outlook.ExplorerEvents_10_FolderSwitchEventHandler(_Explorer_FolderSwitch);

_Explorer.ExplorerEvents_Event_Close += new Microsoft.Office.Interop.Outlook.ExplorerEvents_CloseEventHandler(_Explorer_ExplorerEvents_Event_Close);

}

}

catch (System.Exception ex)

{

// log the error always

Trace.TraceError("{0}: [class]:{1} [method]:{2}\n[message]:{3}\n[Stack]:\n{4}",

DateTime.Now, // when was the error happened

MethodInfo.GetCurrentMethod().DeclaringType.Name, // the class name

MethodInfo.GetCurrentMethod().Name, // the method name

ex.Message, // the error message

ex.StackTrace // the stack trace information

);

// throw the Exception to the calling class

throw ex;

}

}

#endregion

/// <summary>

/// This event occures when this explorer has been closed.

/// </summary>

void _Explorer_ExplorerEvents_Event_Close()

{

// here we release all references to the explorer from memory.

_Explorer.FolderSwitch -= new Microsoft.Office.Interop.Outlook.ExplorerEvents_10_FolderSwitchEventHandler(_Explorer_FolderSwitch);

_Explorer.ExplorerEvents_Event_Close -= new Microsoft.Office.Interop.Outlook.ExplorerEvents_CloseEventHandler(_Explorer_ExplorerEvents_Event_Close);

_Explorer = null;

// fire an event to inform the application that this explorer has been closed.

if (ExplorerClosed != null)

{

ExplorerClosed(this._Id);

}

}

/// <summary>

/// This event occures when another folder has been selected in this explorer.

/// </summary>

void _Explorer_FolderSwitch()

{

try

{

// We change the application menu depending on what folder we have selected

// ModifyMenu();

}

catch (System.Exception ex)

{

// log the error always

Trace.TraceError("{0}: [class]:{1} [method]:{2}\n[message]:{3}\n[Stack]:\n{4}",

DateTime.Now, // when was the error happened

MethodInfo.GetCurrentMethod().DeclaringType.Name, // the class name

MethodInfo.GetCurrentMethod().Name, // the method name

ex.Message, // the error message

ex.StackTrace // the stack trace information

);

// now display a friendly error to the user

MessageBox.Show(null, "There was an application error, you should save your work and restart Outlook.",

"OutlookAdminTools",

MessageBoxButtons.OK,

MessageBoxIcon.Error);

}

}

#endregion

}

}






Re: Visual Studio Tools for Office Outlook Explorer Close event

EB78

Thanks Helmut,

I tried to run your code, however i got the same behavior:

When outlook is up the folder switch works fine, but close event not fired when i close the outlook,

When outlook is up and i click right button on some folder and "Open in new window", in the new window

folderSwitch works and also close event fired as well, but when i close the main window (Explorer) the close

event not fired.

Do you have a clue to such strange behavior

Thanks in advance.





Re: Visual Studio Tools for Office Outlook Explorer Close event

Misha Shneerson - MSFT

Hi EB78,

I am the developer on VSTO code who wrote the loader. As I tried to explain earlier, for Outlook 2003 VSTO intercepts the Close event. And, in cases when this Close event is coming from the last Explorer, VSTO unloads the AppDomain your add-in is running in. Consequently, your code is unloaded before it has a chance to receive the Close event. By the way, for Outlook 2007 we do not use the Close event to shutdown the add-in - you will get it there.






Re: Visual Studio Tools for Office Outlook Explorer Close event

EB78

Thanks Misha,

So as i understand if open Outlook and close it the CLose event will not fire.

However peopele get this event even when just one explorer is open, how

I wanted it for cleanup reason and to visible the standart bar (when my AddIn is loaded on folder switch to some folder created by

addin i hide the outlook standart comand bar and show my bar), for next time when user when open the Outlook,

how can i accomplish this

Thanks in advance.





Re: Visual Studio Tools for Office Outlook Explorer Close event

Misha Shneerson - MSFT

You need to use ThisAddin_Shutdown event for your cleanup.




Re: Visual Studio Tools for Office Outlook Explorer Close event

EB78

Thanks MIsha,

Of course in ThisAddin_Shutdown event i perform cleanup, however i can't access Explorers on this stage,

cause probably there are no Explorers, it's too late.

Any suggestion

Thanks in Advance.





Re: Visual Studio Tools for Office Outlook Explorer Close event

Misha Shneerson - MSFT

You do not necessarily need to access Explorer to remove your command bar controls. You can just keep track of the command bar control you have created so far and then delete them on Shutdown. The below code worked for me.

Office.CommandBarControl cbc;

private void ThisAddIn_Startup(object sender, System.EventArgs e)

{

Outlook.Explorer expl = this.Application.Explorers[1];

Office.CommandBar mb = expl.CommandBars["Menu Bar"];

cbc = this.Application.Explorers[1].CommandBars["Menu Bar"].Controls.Add(10, missing, missing, missing, missing);

cbc.Caption = "My Control";

}

private void ThisAddIn_Shutdown(object sender, System.EventArgs e)

{

cbc.Delete(missing);

}






Re: Visual Studio Tools for Office Outlook Explorer Close event

EB78

Thanks Misha,

The second reason i wanted to catch the Explorer's close event is to visible the outlook standart comand bar on Outlook closing,

cause my addIn hide it, and i want that when next time user open the Outlook this bar will on.

Thanks.