VSTO Outlook 2003 - problem with actions

E

Eddie

I tried to build sample plugin using VSTO for Outlook 2003.
I ran into few problems. I hope somebody could answer my questions.

Sample code:
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
explorer = this.Application.ActiveExplorer();
menu = explorer.CommandBars.ActiveMenuBar;
menuButton =
(Office.CommandBarButton)(menu.Controls.Add(Office.MsoControlType.msoControlButton,
Type.Missing, Type.Missing, menu.Controls.Count, true));
menuButton.Caption = "My menu item";
menuButton.Visible = true;
menuButton.Click += new
Microsoft.Office.Core._CommandBarButtonEvents_ClickEventHandler(menuButton_Click);

Outlook.NameSpace ns = Application.GetNamespace("MAPI");
contacts =
ns.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderContacts);
contacts.Items.ItemAdd += new
Microsoft.Office.Interop.Outlook.ItemsEvents_ItemAddEventHandler(Items_ItemAdd);

if (contacts.Items != null)
{
foreach (Outlook.ContactItem conItem in contacts.Items)
{
Outlook.Action action = conItem.Actions["My action"];
if (action == null)
{
action = conItem.Actions.Add();
action.Enabled = true;
action.Name = "My action";
action.ShowOn =
Microsoft.Office.Interop.Outlook.OlActionShowOn.olMenu;

conItem.CustomAction += new
Microsoft.Office.Interop.Outlook.ItemEvents_10_CustomActionEventHandler(conItem_CustomAction);
conItem.Save();
}
}
}
}

void Items_ItemAdd(object Item)
{
// this isn't called, why?
}

void conItem_CustomAction(object Action, object Response, ref bool Cancel)
{
// this is called only once, why?
// when i use my action twice, another - not my - action is performed,
why?

MyForm form = new MyForm();
form.ShowDialog();
Cancel = true;
}

private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
{
// should I free my menuButton and my actions here?
}
 
D

Dmitry Streblechenko

1. Why do you expect Items.ItemAdd event to fire? You are not addng new
items to the Contacts folder.

2. Items collection must be stored in a class member to make sure it is
alive at all times. You do not have even a local variable, only an implicit
one created by the
contacts.Items.ItemAdd += new ...
As soon as GC runs, that implicit variable will be release and you will
never get any events. You need something like

Outlook.Items Items; //must a class member
....
Items = contacts.Items;
Items.ItemAdd += new ...

3. conItem will end up pointing to the last item in the foreach loop.
Similar to #2, you need to store the items that you need to sink events from
in a list to make sure they are alive. You cannot use a single variable,
each item must be stored separately and be alive as long as you trakc the
events. Also note that sinking events from potemtially thousands of items is
a terrible idea.

4. In your CustomAction event handler you never even check *which* custom
action is firing. At the very least, check the Action.Name property to make
sure you get the expected action.

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

Eddie said:
I tried to build sample plugin using VSTO for Outlook 2003.
I ran into few problems. I hope somebody could answer my questions.

Sample code:
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
explorer = this.Application.ActiveExplorer();
menu = explorer.CommandBars.ActiveMenuBar;
menuButton =
(Office.CommandBarButton)(menu.Controls.Add(Office.MsoControlType.msoControlButton,
Type.Missing, Type.Missing, menu.Controls.Count, true));
menuButton.Caption = "My menu item";
menuButton.Visible = true;
menuButton.Click += new
Microsoft.Office.Core._CommandBarButtonEvents_ClickEventHandler(menuButton_Click);

Outlook.NameSpace ns = Application.GetNamespace("MAPI");
contacts =
ns.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderContacts);
contacts.Items.ItemAdd += new
Microsoft.Office.Interop.Outlook.ItemsEvents_ItemAddEventHandler(Items_ItemAdd);

if (contacts.Items != null)
{
foreach (Outlook.ContactItem conItem in contacts.Items)
{
Outlook.Action action = conItem.Actions["My action"];
if (action == null)
{
action = conItem.Actions.Add();
action.Enabled = true;
action.Name = "My action";
action.ShowOn =
Microsoft.Office.Interop.Outlook.OlActionShowOn.olMenu;

conItem.CustomAction += new
Microsoft.Office.Interop.Outlook.ItemEvents_10_CustomActionEventHandler(conItem_CustomAction);
conItem.Save();
}
}
}
}

void Items_ItemAdd(object Item)
{
// this isn't called, why?
}

void conItem_CustomAction(object Action, object Response, ref bool Cancel)
{
// this is called only once, why?
// when i use my action twice, another - not my - action is performed,
why?

MyForm form = new MyForm();
form.ShowDialog();
Cancel = true;
}

private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
{
// should I free my menuButton and my actions here?
}
 
E

Eddie

Hi there!

Yes, I'm adding new items at runtime manually. I think there shouldn't be
any problems with it.

I agree with You. Putting all my contacts into some collection object isn't
a good idea. I found some examples which are showing context menu
modification, just before they get fired.

This sample i saw, was made using Application_ItemCOntextMenu. But my
application object don't have this event.

I fought my CustomAction is only fired by action which I created, because my
event handler is added only to it.

I think all my problems are bacause GC, gets my objects.

I will try to fix it using your hints.
Thank you, for your help.

Dmitry Streblechenko said:
1. Why do you expect Items.ItemAdd event to fire? You are not addng new
items to the Contacts folder.

2. Items collection must be stored in a class member to make sure it is
alive at all times. You do not have even a local variable, only an implicit
one created by the
contacts.Items.ItemAdd += new ...
As soon as GC runs, that implicit variable will be release and you will
never get any events. You need something like

Outlook.Items Items; //must a class member
....
Items = contacts.Items;
Items.ItemAdd += new ...

3. conItem will end up pointing to the last item in the foreach loop.
Similar to #2, you need to store the items that you need to sink events from
in a list to make sure they are alive. You cannot use a single variable,
each item must be stored separately and be alive as long as you trakc the
events. Also note that sinking events from potemtially thousands of items is
a terrible idea.

4. In your CustomAction event handler you never even check *which* custom
action is firing. At the very least, check the Action.Name property to make
sure you get the expected action.

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

Eddie said:
I tried to build sample plugin using VSTO for Outlook 2003.
I ran into few problems. I hope somebody could answer my questions.

Sample code:
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
explorer = this.Application.ActiveExplorer();
menu = explorer.CommandBars.ActiveMenuBar;
menuButton =
(Office.CommandBarButton)(menu.Controls.Add(Office.MsoControlType.msoControlButton,
Type.Missing, Type.Missing, menu.Controls.Count, true));
menuButton.Caption = "My menu item";
menuButton.Visible = true;
menuButton.Click += new
Microsoft.Office.Core._CommandBarButtonEvents_ClickEventHandler(menuButton_Click);

Outlook.NameSpace ns = Application.GetNamespace("MAPI");
contacts =
ns.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderContacts);
contacts.Items.ItemAdd += new
Microsoft.Office.Interop.Outlook.ItemsEvents_ItemAddEventHandler(Items_ItemAdd);

if (contacts.Items != null)
{
foreach (Outlook.ContactItem conItem in contacts.Items)
{
Outlook.Action action = conItem.Actions["My action"];
if (action == null)
{
action = conItem.Actions.Add();
action.Enabled = true;
action.Name = "My action";
action.ShowOn =
Microsoft.Office.Interop.Outlook.OlActionShowOn.olMenu;

conItem.CustomAction += new
Microsoft.Office.Interop.Outlook.ItemEvents_10_CustomActionEventHandler(conItem_CustomAction);
conItem.Save();
}
}
}
}

void Items_ItemAdd(object Item)
{
// this isn't called, why?
}

void conItem_CustomAction(object Action, object Response, ref bool Cancel)
{
// this is called only once, why?
// when i use my action twice, another - not my - action is performed,
why?

MyForm form = new MyForm();
form.ShowDialog();
Cancel = true;
}

private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
{
// should I free my menuButton and my actions here?
}
 
E

Eddie

Hi there!

Yes, I'm adding new items at runtime manually. I think there shouldn't be
any problems with it.

I agree with You. Putting all my contacts into some collection object isn't
a good idea. I found some examples which are showing context menu
modification, just before they get fired.

This sample i saw, was made using Application_ItemCOntextMenu. But my
application object don't have this event.

I fought my CustomAction is only fired by action which I created, because my
event handler is added only to it.

I think all my problems are because GC, gets my objects.

I will try to fix it using your hints.
Thank you, for your help.

Dmitry Streblechenko said:
1. Why do you expect Items.ItemAdd event to fire? You are not addng new
items to the Contacts folder.

2. Items collection must be stored in a class member to make sure it is
alive at all times. You do not have even a local variable, only an implicit
one created by the
contacts.Items.ItemAdd += new ...
As soon as GC runs, that implicit variable will be release and you will
never get any events. You need something like

Outlook.Items Items; //must a class member
....
Items = contacts.Items;
Items.ItemAdd += new ...

3. conItem will end up pointing to the last item in the foreach loop.
Similar to #2, you need to store the items that you need to sink events from
in a list to make sure they are alive. You cannot use a single variable,
each item must be stored separately and be alive as long as you trakc the
events. Also note that sinking events from potemtially thousands of items is
a terrible idea.

4. In your CustomAction event handler you never even check *which* custom
action is firing. At the very least, check the Action.Name property to make
sure you get the expected action.

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

Eddie said:
I tried to build sample plugin using VSTO for Outlook 2003.
I ran into few problems. I hope somebody could answer my questions.

Sample code:
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
explorer = this.Application.ActiveExplorer();
menu = explorer.CommandBars.ActiveMenuBar;
menuButton =
(Office.CommandBarButton)(menu.Controls.Add(Office.MsoControlType.msoControlButton,
Type.Missing, Type.Missing, menu.Controls.Count, true));
menuButton.Caption = "My menu item";
menuButton.Visible = true;
menuButton.Click += new
Microsoft.Office.Core._CommandBarButtonEvents_ClickEventHandler(menuButton_Click);

Outlook.NameSpace ns = Application.GetNamespace("MAPI");
contacts =
ns.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderContacts);
contacts.Items.ItemAdd += new
Microsoft.Office.Interop.Outlook.ItemsEvents_ItemAddEventHandler(Items_ItemAdd);

if (contacts.Items != null)
{
foreach (Outlook.ContactItem conItem in contacts.Items)
{
Outlook.Action action = conItem.Actions["My action"];
if (action == null)
{
action = conItem.Actions.Add();
action.Enabled = true;
action.Name = "My action";
action.ShowOn =
Microsoft.Office.Interop.Outlook.OlActionShowOn.olMenu;

conItem.CustomAction += new
Microsoft.Office.Interop.Outlook.ItemEvents_10_CustomActionEventHandler(conItem_CustomAction);
conItem.Save();
}
}
}
}

void Items_ItemAdd(object Item)
{
// this isn't called, why?
}

void conItem_CustomAction(object Action, object Response, ref bool Cancel)
{
// this is called only once, why?
// when i use my action twice, another - not my - action is performed,
why?

MyForm form = new MyForm();
form.ShowDialog();
Cancel = true;
}

private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
{
// should I free my menuButton and my actions here?
}
 
D

Dmitry Streblechenko

Context menu events are only exposed in Outlook 2007, not in any previous
version of Outlook.

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

Eddie said:
Hi there!

Yes, I'm adding new items at runtime manually. I think there shouldn't be
any problems with it.

I agree with You. Putting all my contacts into some collection object
isn't
a good idea. I found some examples which are showing context menu
modification, just before they get fired.

This sample i saw, was made using Application_ItemCOntextMenu. But my
application object don't have this event.

I fought my CustomAction is only fired by action which I created, because
my
event handler is added only to it.

I think all my problems are because GC, gets my objects.

I will try to fix it using your hints.
Thank you, for your help.

Dmitry Streblechenko said:
1. Why do you expect Items.ItemAdd event to fire? You are not addng new
items to the Contacts folder.

2. Items collection must be stored in a class member to make sure it is
alive at all times. You do not have even a local variable, only an
implicit
one created by the
contacts.Items.ItemAdd += new ...
As soon as GC runs, that implicit variable will be release and you will
never get any events. You need something like

Outlook.Items Items; //must a class member
....
Items = contacts.Items;
Items.ItemAdd += new ...

3. conItem will end up pointing to the last item in the foreach loop.
Similar to #2, you need to store the items that you need to sink events
from
in a list to make sure they are alive. You cannot use a single variable,
each item must be stored separately and be alive as long as you trakc the
events. Also note that sinking events from potemtially thousands of items
is
a terrible idea.

4. In your CustomAction event handler you never even check *which* custom
action is firing. At the very least, check the Action.Name property to
make
sure you get the expected action.

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

Eddie said:
I tried to build sample plugin using VSTO for Outlook 2003.
I ran into few problems. I hope somebody could answer my questions.

Sample code:
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
explorer = this.Application.ActiveExplorer();
menu = explorer.CommandBars.ActiveMenuBar;
menuButton =
(Office.CommandBarButton)(menu.Controls.Add(Office.MsoControlType.msoControlButton,
Type.Missing, Type.Missing, menu.Controls.Count, true));
menuButton.Caption = "My menu item";
menuButton.Visible = true;
menuButton.Click += new
Microsoft.Office.Core._CommandBarButtonEvents_ClickEventHandler(menuButton_Click);

Outlook.NameSpace ns = Application.GetNamespace("MAPI");
contacts =
ns.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderContacts);
contacts.Items.ItemAdd += new
Microsoft.Office.Interop.Outlook.ItemsEvents_ItemAddEventHandler(Items_ItemAdd);

if (contacts.Items != null)
{
foreach (Outlook.ContactItem conItem in contacts.Items)
{
Outlook.Action action = conItem.Actions["My action"];
if (action == null)
{
action = conItem.Actions.Add();
action.Enabled = true;
action.Name = "My action";
action.ShowOn =
Microsoft.Office.Interop.Outlook.OlActionShowOn.olMenu;

conItem.CustomAction += new
Microsoft.Office.Interop.Outlook.ItemEvents_10_CustomActionEventHandler(conItem_CustomAction);
conItem.Save();
}
}
}
}

void Items_ItemAdd(object Item)
{
// this isn't called, why?
}

void conItem_CustomAction(object Action, object Response, ref bool
Cancel)
{
// this is called only once, why?
// when i use my action twice, another - not my - action is
performed,
why?

MyForm form = new MyForm();
form.ShowDialog();
Cancel = true;
}

private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
{
// should I free my menuButton and my actions here?
}
 

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