Inspector_Close after Item_Send not firing

G

g62msdnatll

I have a C# COM add-in
Windows XP
Outlook 2003

When I send an item, the Item_Send event fires, but Inspector_Close does not.

In documentation (I only have documentation up to Outlook 2002), it seems
this is NOT the specified and documented behavior.

The Item_Send event merely logs a line to a file. The Inspector_Deactivate
event spawns a short-lived thread to check what process is active when the
Inspector is deactivated.

If I open a new_inspector and then close without sending, I get the
Inspector_Close event.

I need the Inspector_Close event to fire so that I know to update my
collection of Inspector objects and release dead inspectors.

Help?
 
H

Helmut Obertanner

Hello,

it seems that you had created a reference to the Inspector object and didn't
release it correctly. (Marshal.ReleaseComObject)
If the Inspectorobject isn't released, it can't close.

Maybe give as a codesnippet to see what's happen when you handle the send
event.

Hope this helps.

--
Helmut Obertanner
Technical Consultant
Softwaredevelopment
DATALOG Software AG | Zschokkestr. 36 | D-80687 Munich

.... and IT works!
 
G

g62msdnatll

Hi,

Here is the Item_Send event handler:

public static void outlookApp_ItemSend(object Item, ref bool Cancel)
{

OutlookLogger.LogItemSendEvent(Connect.fn, Item);
Marshal.ReleaseComObject(Item);
}

Here is LogItemSendEvent:

public static void LogItemSendEvent(string filename, object Item)
{
Collections.StringCollection strCollection = new
System.Collections.Specialized.StringCollection();

strCollection.Add(LogType.Event_Item_Send);

try
{
Append(ref strCollection, OutlookMonitorUtility.GetItemInfo(Item));
}
catch (System.Exception e)
{
LogError(filename, "LogItemSendEvent"+ Delimiter() + e.Message);
}
Log(filename, strCollection);
LogFolderStatistics(filename, Connect.outlookApp);
}

Here is OutlookMonitorUtility.GetItemInfo(Item):

public static Collections.StringCollection GetItemInfo(object Item)
{
Collections.StringCollection strCollection = new
System.Collections.Specialized.StringCollection();

if (Item is MailItem)
{
//BASICALLY ACCESS ALL THE FIELDS OF THE ITEM
}
}

I do not release the MailItem, but I do release the Inspector.

Can you see the problem from these snippets?

Thank you for your help!
 
P

Peter Huang [MSFT]

Hi

Here is my test sample which works on my side.
You may have a try.

public void OnConnection(object application, Extensibility.ext_ConnectMode
connectMode, object addInInst, ref System.Array custom)
{
olApp = application as Outlook.Application;
olApp.ItemSend+=new
Microsoft.Office.Interop.Outlook.ApplicationEvents_11_ItemSendEventHandler(o
lApp_ItemSend);
olApp.Inspectors.NewInspector+=new
Microsoft.Office.Interop.Outlook.InspectorsEvents_NewInspectorEventHandler(I
nspectors_NewInspector);
}

private Outlook.Application olApp = null;

private void olApp_ItemSend(object Item, ref bool Cancel)
{
Debug.WriteLine("olApp_ItemSend");
}

private void
Inspectors_NewInspector(Microsoft.Office.Interop.Outlook.Inspector
Inspector)
{
Debug.WriteLine("Inspectors_NewInspector");
((Outlook.InspectorEvents_10_Event)Inspector).Close+=new
Microsoft.Office.Interop.Outlook.InspectorEvents_10_CloseEventHandler(Connec
t_Close);
}

private void Connect_Close()
{
Debug.WriteLine("Connect_Close");
}
}

Best regards,

Peter Huang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
 
H

Helmut Obertanner

Hello,

i didn't see an Inspector Object in the snippets.
The Item Send event you used comes from Application Object not from Item or

I don't know how did you handle your Inspector Object.

I have also some samples wich you can have a look into here:

Saving sent Email Information into XML
http://www.outlookcode.com/codedetail.aspx?id=767

Inspector wrapper sample
http://www.outlookcode.com/codedetail.aspx?id=797

Maybe it's usefull to you.

--
Helmut Obertanner
Technical Consultant
Softwaredevelopment
DATALOG Software AG | Zschokkestr. 36 | D-80687 Munich

.... and IT works!
 
G

g62msdnatll

I have put this in my code, and I am still not getting the Inspector_Close
after Item_Send.
 
P

Peter Huang [MSFT]

Hi

For clarification, I post the whole code in my test.

I think you may try to check if you have installed office PIA.
NOTE: Office 2003 PIA shipped with office install program.
Office XP PIA is downloaded in the link below.
http://www.microsoft.com/downloads/details.aspx?FamilyId=C41BD61E-3060-4F71-
A6B4-01FEBA508E52&displaylang=en

Also you may try the same code at another machine.

namespace OutlookAddin_InspectorEvent
{
using System;
using Microsoft.Office.Core;
using Extensibility;
using System.Runtime.InteropServices;
using Outlook = Microsoft.Office.Interop.Outlook;
using System.Diagnostics;

#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("EE87506A-A949-4BB6-97C3-857BFF31112C"),
ProgId("OutlookAddin_InspectorEvent.Connect")]
public class Connect : Object, Extensibility.IDTExtensibility2
{
/// <summary>
/// Implements the constructor for the Add-in object.
/// Place your initialization code within this method.
/// </summary>
public Connect()
{
}

/// <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)
{
olApp = application as Outlook.Application;
olApp.ItemSend+=new
Microsoft.Office.Interop.Outlook.ApplicationEvents_11_ItemSendEventHandler(o
lApp_ItemSend);
olApp.Inspectors.NewInspector+=new
Microsoft.Office.Interop.Outlook.InspectorsEvents_NewInspectorEventHandler(I
nspectors_NewInspector);
// applicationObject = application;
// addInInstance = 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)
{
}

/// <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)
{
}

/// <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)
{
}
// private object applicationObject;
// private object addInInstance;
private Outlook.Application olApp = null;

private void olApp_ItemSend(object Item, ref bool Cancel)
{
Debug.WriteLine("olApp_ItemSend");
}

private void
Inspectors_NewInspector(Microsoft.Office.Interop.Outlook.Inspector
Inspector)
{
Debug.WriteLine("Inspectors_NewInspector");
((Outlook.InspectorEvents_10_Event)Inspector).Close+=new
Microsoft.Office.Interop.Outlook.InspectorEvents_10_CloseEventHandler(Connec
t_Close);
}

private void Connect_Close()
{
Debug.WriteLine("Connect_Close");
}
}
}

Best regards,

Peter Huang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
 
H

Helmut Obertanner

Hello Peter,

your code snippet is fine, except that you didn't remember the Inspector
Object in your new_Inspector eventhandler.
As soon as the GarbageCollector does a cleanup, the close event won't come
anymore, because the Inspector Object in the eventhandler isn't referenced.

What do you think ?

best regards
--
Helmut Obertanner
Technical Consultant
Softwaredevelopment
DATALOG Software AG | Zschokkestr. 36 | D-80687 Munich

.... and IT works!



"Peter Huang" said:
Hi

For clarification, I post the whole code in my test.

I think you may try to check if you have installed office PIA.
NOTE: Office 2003 PIA shipped with office install program.
Office XP PIA is downloaded in the link below.
http://www.microsoft.com/downloads/details.aspx?FamilyId=C41BD61E-3060-4F71-
A6B4-01FEBA508E52&displaylang=en

Also you may try the same code at another machine.

namespace OutlookAddin_InspectorEvent
{
using System;
using Microsoft.Office.Core;
using Extensibility;
using System.Runtime.InteropServices;
using Outlook = Microsoft.Office.Interop.Outlook;
using System.Diagnostics;

#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("EE87506A-A949-4BB6-97C3-857BFF31112C"),
ProgId("OutlookAddin_InspectorEvent.Connect")]
public class Connect : Object, Extensibility.IDTExtensibility2
{
/// <summary>
/// Implements the constructor for the Add-in object.
/// Place your initialization code within this method.
/// </summary>
public Connect()
{
}

/// <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)
{
olApp = application as Outlook.Application;
olApp.ItemSend+=new
Microsoft.Office.Interop.Outlook.ApplicationEvents_11_ItemSendEventHandler(o
lApp_ItemSend);
olApp.Inspectors.NewInspector+=new
Microsoft.Office.Interop.Outlook.InspectorsEvents_NewInspectorEventHandler(I
nspectors_NewInspector);
// applicationObject = application;
// addInInstance = 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)
{
}

/// <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)
{
}

/// <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)
{
}
// private object applicationObject;
// private object addInInstance;
private Outlook.Application olApp = null;

private void olApp_ItemSend(object Item, ref bool Cancel)
{
Debug.WriteLine("olApp_ItemSend");
}

private void
Inspectors_NewInspector(Microsoft.Office.Interop.Outlook.Inspector
Inspector)
{
Debug.WriteLine("Inspectors_NewInspector");
((Outlook.InspectorEvents_10_Event)Inspector).Close+=new
Microsoft.Office.Interop.Outlook.InspectorEvents_10_CloseEventHandler(Connec
t_Close);
}

private void Connect_Close()
{
Debug.WriteLine("Connect_Close");
}
}
}

Best regards,

Peter Huang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
 
K

Ken Slovak - [MVP - Outlook]

Whether or not Inspector_Close and/or MailItem_Close fires after Send
depends on whether or not WordMail is being used. Different events would
fire and in different orders depending on the email editor used.

What I usually do is check for WordMail and use code in both the item and
Inspector close events to call whatever code I want to run or my release
code. You can also use a construct like:

If m_blnWord Then
Inspector.WordEditor.Close wdDoNotSaveChanges
Else
m_objInsp.Close olDiscard
End If

in Item_Send to force one of the other events to fire if you are
intercepting Send and canceling it.
 
P

Peter Huang [MSFT]

Hi

My code is for demo only. I think when the Inspector is opened, even the
reference is opened, the Inspector Instance object is still alive.
Sure, if you want to make it more clear, you may as well set it to a class
member inspector var and then assign event to it.

Anyway, what is your concern now? Did the code snippet works for you? Based
on my test, it works on my side.

Best regards,

Peter Huang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
 
H

Helmut Obertanner

Hello Peter,

I's only a Note to your code:

from my expirience it's not enough to register only the Inspector_Close event.
As soon as the GC does a cleanup, the Inspector_CLose event doesn't fire
anymore.

For a .Net Form your code would work fine, but not for a COM Object called
through PIA.

And maybe that could be also the problem for the original post.

best regards
--
Helmut Obertanner
Technical Consultant
Softwaredevelopment
DATALOG Software AG | Zschokkestr. 36 | D-80687 Munich

.... and IT works!
 
G

g62msdnatll

I need instructions on how to run the sample code to view the
Debug.Writeline output.
When I run this code, I don't see any output in the Debug -> Windows ->
Immediate window.

I was running the snippet in my own code, which logs messages to a log file
instead of using the debugger. And this code does not fix my bug,
Inspector_Close is still not firing.

Please provide instructions on how to run the debugger, I have never done
this before.
 
G

g62msdnatll

It should not matter since I am running Outlook 2003, and the Outlook
documentation for 2002 states that Inspector_Close should always fire. So I
am assuming they didn't break this specification for the next version of
Outlook.

Besides, the Inspector_Close event fires if I create a New_Inspector and
close without sending. So there's no reason why it shouldn't fire as
specified after the Item_Send event.
 
G

g62msdnatll

I figured out how to run the debugger.

This code does not work for me. I still do not get Item_Close after
Item_Send.
 
G

g62msdnatll

I found a potential problem:

When the Item_Send event fires, the item gets put into the Outbox and
doesn't actually get sent.

And I found that the Item_Close event does fire, but only upon exiting
Outlook, so the Item_Close event is very lagged.

This goes back to my previous issue, where items are not being sent , and
are instead getting stuck in the Outbox.
 
P

Peter Huang [MSFT]

Hi

Thanks for your quickly reply!
If you still have any concern, please feel free to post here.

Best regards,

Peter Huang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
 
G

g62msdnatll

The problem has not been resolved. I posted the problems I have with the
code on 7/31.
 
P

Peter Huang [MSFT]

Hi

I am sorry if I did not make it clear.
The code snippet I posted before will work well at my side.
To confirm with the problem can you provide your problem solution and
package in a zip file as an attatchment, so that I may try to reproduce at
my side.

Thanks!

Best regards,

Peter Huang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
 
K

Ken Slovak - [MVP - Outlook]

I said that whether or not Item.Close or Inspector.Close fires depends on
whether or not WordMail is being used and whether or not Send is called,
either in code or from the UI. No matter what the docs say that is true. You
have to handle the various events with tests for WordMail running to cover
all the bases.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top