ItemAdd and ItemRemove not firing properly

N

Neetu

We are using VSTO and C# for creation of an outlook add-in for 2003 and 2007.
Custom Folders are adding inside outlook after task folder.
each folder items are attached with two events Itemadd and Itemremove.
For 2007 events are firing properly however same code is not working for 2003.

private void AttachAddEvent()
{
try
{
if (_mfEmailReceivedList != null)
{
if (_mfEmailReceivedList.Length > 0)
{
for (int i = 0; i < _mfEmailReceivedList.Length; i++)
{
_mfEmailReceivedList.Items.ItemAdd += new
ItemsEvents_ItemAddEventHandler(Items_ItemAdd);
}
}
}

}
catch (System.Exception ex)
{
throw ex;
}
}



mfEmailReceivedList is global object of type MAPIFolder which stores all
folders created inside outlook by our addin.


public void Items_ItemAdd(object item)
{
try
{
if (item is MailItem)
{
_objMail = new Mail(); /// our class for database
operation.
_objMail.Insert((MailItem)item);
_objMail =null;

}
}
catch (System.Exception ex)
{
ShowMessage(ex.ToString(), ex.Source);
}
}

same code we are implementing for 2003 n 2007.
in 2003 events gets fire 1 in 100 attempt. and that is also only one time
in debug or intallation mode.

Any Suggestion or help will be helpful for us to resolve our issue.

Thanks In advance
 
K

Ken Slovak - [MVP - Outlook]

What version of Outlook are you referencing in your project? What version of
Outlook is installed on your development machine? For Outlook 2003 you would
need to develop on an Outlook 2003 development system and the project would
need to reference the Outlook 2003 PIA.

So you are positive that your items for each event handler aren't being
garbage collected or going out of scope before the items are released?
 
D

Dmitry Streblechenko

The line
_mfEmailReceivedList.Items.ItemAdd += new
ItemsEvents_ItemAddEventHandler(Items_ItemAdd);

will sure cause the items colelction to be garbage collected.

Dmitry Streblechenko (MVP)
http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool

Ken Slovak - said:
What version of Outlook are you referencing in your project? What version
of Outlook is installed on your development machine? For Outlook 2003 you
would need to develop on an Outlook 2003 development system and the
project would need to reference the Outlook 2003 PIA.

So you are positive that your items for each event handler aren't being
garbage collected or going out of scope before the items are released?




Neetu said:
We are using VSTO and C# for creation of an outlook add-in for 2003 and
2007.
Custom Folders are adding inside outlook after task folder.
each folder items are attached with two events Itemadd and Itemremove.
For 2007 events are firing properly however same code is not working for
2003.

private void AttachAddEvent()
{
try
{
if (_mfEmailReceivedList != null)
{
if (_mfEmailReceivedList.Length > 0)
{
for (int i = 0; i < _mfEmailReceivedList.Length;
i++)
{
_mfEmailReceivedList.Items.ItemAdd += new
ItemsEvents_ItemAddEventHandler(Items_ItemAdd);
}
}
}

}
catch (System.Exception ex)
{
throw ex;
}
}



mfEmailReceivedList is global object of type MAPIFolder which stores
all
folders created inside outlook by our addin.


public void Items_ItemAdd(object item)
{
try
{
if (item is MailItem)
{
_objMail = new Mail(); /// our class for database
operation.
_objMail.Insert((MailItem)item);
_objMail =null;

}
}
catch (System.Exception ex)
{
ShowMessage(ex.ToString(), ex.Source);
}
}

same code we are implementing for 2003 n 2007.
in 2003 events gets fire 1 in 100 attempt. and that is also only one
time
in debug or intallation mode.

Any Suggestion or help will be helpful for us to resolve our issue.

Thanks In advance

 
N

Neetu

We are using two different VSTO projects.
One for running with Outlook 2007 (New Project > C# >Office >2005 Addins),
and the other for Outlook 2003 (New Project > C# >Office >2003 Addins).

And furthermore, we are developing these two projects in two different
machines.
One machine has VS2005/Outlook 2007/ Outlook 2007 PIA.
The other has VS2005/Outlook 2003/ Outlook 2003 PIA

But the program logic are same (code copy/paste)
ItemAdd and ItemRemove events are getting fired in Outlook 2007 project and
is not getting fired in the machine which runs in Outlook 2003.

We are Using a Array to hold all folders at global level.

Can you please tell us why.



Ken Slovak - said:
What version of Outlook are you referencing in your project? What version of
Outlook is installed on your development machine? For Outlook 2003 you would
need to develop on an Outlook 2003 development system and the project would
need to reference the Outlook 2003 PIA.

So you are positive that your items for each event handler aren't being
garbage collected or going out of scope before the items are released?




Neetu said:
We are using VSTO and C# for creation of an outlook add-in for 2003 and
2007.
Custom Folders are adding inside outlook after task folder.
each folder items are attached with two events Itemadd and Itemremove.
For 2007 events are firing properly however same code is not working for
2003.

private void AttachAddEvent()
{
try
{
if (_mfEmailReceivedList != null)
{
if (_mfEmailReceivedList.Length > 0)
{
for (int i = 0; i < _mfEmailReceivedList.Length;
i++)
{
_mfEmailReceivedList.Items.ItemAdd += new
ItemsEvents_ItemAddEventHandler(Items_ItemAdd);
}
}
}

}
catch (System.Exception ex)
{
throw ex;
}
}



mfEmailReceivedList is global object of type MAPIFolder which stores
all
folders created inside outlook by our addin.


public void Items_ItemAdd(object item)
{
try
{
if (item is MailItem)
{
_objMail = new Mail(); /// our class for database
operation.
_objMail.Insert((MailItem)item);
_objMail =null;

}
}
catch (System.Exception ex)
{
ShowMessage(ex.ToString(), ex.Source);
}
}

same code we are implementing for 2003 n 2007.
in 2003 events gets fire 1 in 100 attempt. and that is also only one time
in debug or intallation mode.

Any Suggestion or help will be helpful for us to resolve our issue.

Thanks In advance

 
K

Ken Slovak - [MVP - Outlook]

As Dmitry mentioned that will lead to garbage collection and your event
handlers going out of scope and being removed, therefore failing to fire.

What you really should do is to create a wrapper class for the folders, one
class instance for each folder you are monitoring.

In the wrapper class you instantiate a folder object and set up and handle
the events for the folder. You can also instantiate an Items collection for
the folder and handle Items events such as ItemAdd. Then you add the wrapper
class to a list or array or collection or whatever to keep the class alive
and therefore also any events handled in the class.

You can see the technique at work, not for folders, but for Inspectors and
Explorers, in my Outlook 2007 templates at
http://www.slovaktech.com/outlook_2007_templates.htm. There are also
Inspector and Explorer wrapper samples, and probably other wrapper class
samples, at www.outlookcode.com.

That way your events will remain alive until you explicitly release them.
 
N

Neetu

We have created a wrapper class for folder..

internal class FolderWrapper
{

int _Id;

public int ID
{

get { return _Id; }

}

Microsoft.Office.Interop.Outlook.MAPIFolder _folder;

public Microsoft.Office.Interop.Outlook.MAPIFolder folder
{

get { return _folder; }

}

object _Missing = System.Reflection.Missing.Value;

public FolderWrapper(int index,
Microsoft.Office.Interop.Outlook.MAPIFolder folder)
{

try
{
_Id = index;
_folder = folder as
Microsoft.Office.Interop.Outlook.MAPIFolder;
if (_folder != null)
{
_folder.Items.ItemAdd += new
Microsoft.Office.Interop.Outlook.ItemsEvents_ItemAddEventHandler(FolderItem_Add);
_folder.Items.ItemRemove += new
Microsoft.Office.Interop.Outlook.ItemsEvents_ItemRemoveEventHandler(FolderItem_Remove);
}
}

catch (System.Exception ex)
{

}
}

public void FolderItem_Add(object item)
{
if (item is MailItem)
{
// do some operation
}
}

public void FolderItem_Remove()
{
try
{
// do some operation
}
catch (System.Exception ex)
{


}
}


This Is inside ThisAddIn where we are initializing our wrapper class
ReceivedList is array list which holds all MAPIFolders

void WrapFolders(MAPIFolder[] ReceivedList)
{
FolderWrapper wrappedFolder;
MAPIFolder ofolder;
_WrapperFolder = new Hashtable(); /// Global variable at
ThisAddIn class
int i = 0;

if (ReceivedList != null)
{
if (ReceivedList.Length > 0)
{
for (i = 0; i < ReceivedList.Length; i++)
{
ofolder = ReceivedList;
wrappedFolder = new FolderWrapper(i, ofolder);
_WrapperFolder.Add(i, wrappedFolder);
}
}
}
}
We are able to create wrapper class for all folders however events are not
firing.
We also tried to create a Folderclass Inside of MAPIFolder for wrapper class
but in construtor when we are assigning like this


if _folder is defined as Microsoft.Office.Interop.Outlook.FolderClass

_folder = folder as Microsoft.Office.Interop.Outlook.FolderClass;

then
_folder is always null.

our hasttable is accessible all the time of outlook session with all correct
values of folders.

Is the way we are creating our wrapper class is correct or do we need to
something else??


Kindly Help us.

Thanks in advance
 
K

Ken Slovak - [MVP - Outlook]

Try declaring a class level object for the folder's Items collection and
using that when instantiating the Items event handlers, see if that helps:

internal class FolderWrapper
{

int _Id;

// etc.

Microsoft.Office.Interop.Outlook.Items _items;


// blah, blah

_items.ItemAdd += new
microsoft.Office.Interop.Outlook.ItemsEvents_ItemAddEventHandler(FolderItem_Add);

// blah, blah




Neetu said:
We have created a wrapper class for folder..

internal class FolderWrapper
{

int _Id;

public int ID
{

get { return _Id; }

}

Microsoft.Office.Interop.Outlook.MAPIFolder _folder;

public Microsoft.Office.Interop.Outlook.MAPIFolder folder
{

get { return _folder; }

}

object _Missing = System.Reflection.Missing.Value;

public FolderWrapper(int index,
Microsoft.Office.Interop.Outlook.MAPIFolder folder)
{

try
{
_Id = index;
_folder = folder as
Microsoft.Office.Interop.Outlook.MAPIFolder;
if (_folder != null)
{
_folder.Items.ItemAdd += new
Microsoft.Office.Interop.Outlook.ItemsEvents_ItemAddEventHandler(FolderItem_Add);
_folder.Items.ItemRemove += new
Microsoft.Office.Interop.Outlook.ItemsEvents_ItemRemoveEventHandler(FolderItem_Remove);
}
}

catch (System.Exception ex)
{

}
}

public void FolderItem_Add(object item)
{
if (item is MailItem)
{
// do some operation
}
}

public void FolderItem_Remove()
{
try
{
// do some operation
}
catch (System.Exception ex)
{


}
}


This Is inside ThisAddIn where we are initializing our wrapper class
ReceivedList is array list which holds all MAPIFolders

void WrapFolders(MAPIFolder[] ReceivedList)
{
FolderWrapper wrappedFolder;
MAPIFolder ofolder;
_WrapperFolder = new Hashtable(); /// Global variable at
ThisAddIn class
int i = 0;

if (ReceivedList != null)
{
if (ReceivedList.Length > 0)
{
for (i = 0; i < ReceivedList.Length; i++)
{
ofolder = ReceivedList;
wrappedFolder = new FolderWrapper(i, ofolder);
_WrapperFolder.Add(i, wrappedFolder);
}
}
}
}
We are able to create wrapper class for all folders however events are not
firing.
We also tried to create a Folderclass Inside of MAPIFolder for wrapper
class
but in construtor when we are assigning like this


if _folder is defined as Microsoft.Office.Interop.Outlook.FolderClass

_folder = folder as Microsoft.Office.Interop.Outlook.FolderClass;

then
_folder is always null.

our hasttable is accessible all the time of outlook session with all
correct
values of folders.

Is the way we are creating our wrapper class is correct or do we need to
something else??


Kindly Help us.

Thanks in advance
 
N

Neetu

Hello Ken,

This new change Item property for folder wrapper is working fine with 2007
outlook.
However in 2003, it is working only for itemadd event.
itemremove is not firing.
also after one insertion of a mail from inbox into custom folder , if we
delete it or move to inbox folder , and again if we tries to add same mail
into same custom folder, add event doesn't get fires .
and if we tries to add same item to some other custom folder such errors
msg comes..


"can't move the item.the item couldn't move.it is either moved or deleted,
or access is denied"

we are setting mailitem object =null at each itemadd and itemremove function.




Ken Slovak - said:
Try declaring a class level object for the folder's Items collection and
using that when instantiating the Items event handlers, see if that helps:

internal class FolderWrapper
{

int _Id;

// etc.

Microsoft.Office.Interop.Outlook.Items _items;


// blah, blah

_items.ItemAdd += new
microsoft.Office.Interop.Outlook.ItemsEvents_ItemAddEventHandler(FolderItem_Add);

// blah, blah




Neetu said:
We have created a wrapper class for folder..

internal class FolderWrapper
{

int _Id;

public int ID
{

get { return _Id; }

}

Microsoft.Office.Interop.Outlook.MAPIFolder _folder;

public Microsoft.Office.Interop.Outlook.MAPIFolder folder
{

get { return _folder; }

}

object _Missing = System.Reflection.Missing.Value;

public FolderWrapper(int index,
Microsoft.Office.Interop.Outlook.MAPIFolder folder)
{

try
{
_Id = index;
_folder = folder as
Microsoft.Office.Interop.Outlook.MAPIFolder;
if (_folder != null)
{
_folder.Items.ItemAdd += new
Microsoft.Office.Interop.Outlook.ItemsEvents_ItemAddEventHandler(FolderItem_Add);
_folder.Items.ItemRemove += new
Microsoft.Office.Interop.Outlook.ItemsEvents_ItemRemoveEventHandler(FolderItem_Remove);
}
}

catch (System.Exception ex)
{

}
}

public void FolderItem_Add(object item)
{
if (item is MailItem)
{
// do some operation
}
}

public void FolderItem_Remove()
{
try
{
// do some operation
}
catch (System.Exception ex)
{


}
}


This Is inside ThisAddIn where we are initializing our wrapper class
ReceivedList is array list which holds all MAPIFolders

void WrapFolders(MAPIFolder[] ReceivedList)
{
FolderWrapper wrappedFolder;
MAPIFolder ofolder;
_WrapperFolder = new Hashtable(); /// Global variable at
ThisAddIn class
int i = 0;

if (ReceivedList != null)
{
if (ReceivedList.Length > 0)
{
for (i = 0; i < ReceivedList.Length; i++)
{
ofolder = ReceivedList;
wrappedFolder = new FolderWrapper(i, ofolder);
_WrapperFolder.Add(i, wrappedFolder);
}
}
}
}
We are able to create wrapper class for all folders however events are not
firing.
We also tried to create a Folderclass Inside of MAPIFolder for wrapper
class
but in construtor when we are assigning like this


if _folder is defined as Microsoft.Office.Interop.Outlook.FolderClass

_folder = folder as Microsoft.Office.Interop.Outlook.FolderClass;

then
_folder is always null.

our hasttable is accessible all the time of outlook session with all
correct
values of folders.

Is the way we are creating our wrapper class is correct or do we need to
something else??


Kindly Help us.

Thanks in advance

 
K

Ken Slovak - [MVP - Outlook]

If you get that error it means the object is open in another part of the
code and wasn't released. Otherwise you would not get that error.

I don't know why you're having a problem with Outlook 2003, all those events
work in Outlook 2003 and were working long before Outlook 2007 was a gleam
in MS's eye. My guess is there's some code path that is releasing your
objects or letting them get garbage collected and therefore letting the
events go out of scope.
 
N

Neetu

Hi ken, our additem events get fires for all mails and multiple times.

this is code inside folder wrapper
_items.ItemRemove += new
Microsoft.Office.Interop.Outlook.ItemsEvents_ItemRemoveEventHandler(FolderItem_Remove);

this is public function for add event

public void FolderItem_Add(object item)
{
if (item is MailItem)
{
//database call operation
Item=null;
}
}

Only Things is we are not able to fire add event for a mail more than once.
 
K

Ken Slovak - [MVP - Outlook]

The only reason that a conflict message would be generated is if the item is
being changed in two or more places or a reference to a modified items is
being held somewhere. It could be anywhere in your code.
 
K

Ken Slovak - [MVP - Outlook]

And is your ItemAdd event handler declared the same was as ItemRemove, using
the same _items collection object?
 
N

Neetu

Hello ken,

Its working now. Thanks a lot for this wonderful guidance and information.
In 2003 , if a folder has just 1 mailitem , in that case item remove event
is not firing.
Is this is known bug. or is there any fix for it?

Thanks
Neetu
 
K

Ken Slovak - [MVP - Outlook]

That's a known thing. No fix that I know of. About all you can do in those
cases is sweep the monitored folders at timed intervals and see if
Items.Count == 0.
 
N

Neetu

Some how we resolved our issue for Last item removal from outlook 2003.
In our folder wrapper class we created a static function which checks a
collection object ( static to folderwrapper). if count inside collection is >
0 then we are calling approraite function to call our data base function.this
is function body

public static void DeleteMailExplicitly()
{
MailItem _mailselected = null;
try
{
if (_Selectedmailitemlist == null)
return;
if (_Selectedmailitemlist.Count < 1)
return;
int TotalCount = _Selectedmailitemlist.Count;
for (int index = 0; index < TotalCount; index++)
{
_mailselected = _Selectedmailitemlist[index] as MailItem;
//Database call
Marshal.ReleaseComObject(_mailselected);
_mailselected = null;
}

}
catch (System.Exception ee)
{
}
finally
{
if (_mailselected != null)
{
Marshal.ReleaseComObject(_mailselected);
_mailselected = null;
}

_Selectedmailitemlist.Clear();
}


as soon as we delete our last item from folder , its called Explorer
SelectionChange event
Inside this event we are checking if current selectedfolder is our custom
folder and
if _Explorer.Selection.Count>0
Then Add Mail item inside FolderWrapper mail collection.
else
check is collection.count >0 then
Call static Function 'DeleteMailExplicitly'
end

this flow is working fine with 2003.I hope this will help other outlook
add-in developers also..

Hello Ken, we are thankful for your help and tips.

Neetu
 

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