VSTO Outlook 加载项事件处理程序在启动时未触发
在此处输入代码
我有一个正在拦截自定义事件的 VSTO 添加。我有事件处理程序。我正在 Outlook 的默认日历文件夹中查找添加、编辑和删除项目。
我有一个用于创建自定义约会的按钮,按下该按钮后,事件处理程序可以正常工作,但我需要事件处理程序从启动开始运行以捕获在上一个会话中创建的自定义事件,并且它们并不总是在启动时触发。
这是一些示例代码。
public partial class ThisAddIn
{
public string subjectName;
public Outlook.AppointmentItem apptItem;
public Outlook.Folder calendarFolder;
Outlook.Items items;
bool m_IsFirstTime = false;
CalendarMonitor calendarMonitor;
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
calendarMonitor = new CalendarMonitor(Application.ActiveExplorer());
calendarMonitor.AppointmentAdded += new EventHandler<EventArgs<AppointmentItem>>(Monitor_AppointmentAdded);
calendarMonitor.AppointmentModified += new EventHandler<EventArgs<AppointmentItem>>(Monitor_AppointmentModified);
calendarMonitor.AppointmentDeleting += new EventHandler<CancelEventArgs<AppointmentItem>>(Monitor_AppointmentDeleting);
Application.Inspectors.NewInspector += Inspectors_NewInspector;
Outlook.NameSpace ns = Application.Session;
calendarFolder = ns.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderCalendar) as Outlook.Folder;
items = calendarFolder.Items;
items.ItemChange += new Microsoft.Office.Interop.Outlook.ItemsEvents_ItemChangeEventHandler(Items_ItemChange);
}
}
//Calendar Monitor class
public class CalendarMonitor
{
private Explorer m_explorer;
private List<string> m_folderPaths;
private List<MAPIFolder> m_calendarFolders;
private List<Items> m_calendarItems;
private MAPIFolder m_deletedItemsFolder;
public event EventHandler<EventArgs<AppointmentItem>> AppointmentAdded;
public event EventHandler<EventArgs<AppointmentItem>> AppointmentModified;
public event EventHandler<CancelEventArgs<AppointmentItem>> AppointmentDeleting;
public CalendarMonitor(Explorer anExplorer)
{
m_folderPaths = new List<string>();
m_calendarFolders = new List<MAPIFolder>();
m_calendarItems = new List<Items>();
m_explorer = anExplorer;
m_explorer.BeforeFolderSwitch +=
new ExplorerEvents_10_BeforeFolderSwitchEventHandler(Explorer_BeforeFolderSwitch);
NameSpace session = m_explorer.Session;
try
{
m_deletedItemsFolder = session.GetDefaultFolder(OlDefaultFolders.olFolderDeletedItems);
HookupDefaultCalendarEvents(session);
}
finally
{
Marshal.ReleaseComObject(session);
session = null;
}
}
private void HookupDefaultCalendarEvents(NameSpace aSession)
{
MAPIFolder folder = aSession.GetDefaultFolder(OlDefaultFolders.olFolderCalendar);
if (folder != null)
{
try
{
HookupCalendarEvents(folder);
}
finally
{
Marshal.ReleaseComObject(folder);
folder = null;
}
}
}
private void Explorer_BeforeFolderSwitch(object aNewFolder, ref bool Cancel)
{
MAPIFolder folder = (aNewFolder as MAPIFolder);
//
// Hookup events to any other Calendar folder opened.
//
if (folder != null)
{
try
{
if (folder.DefaultItemType == OlItemType.olAppointmentItem)
{
HookupCalendarEvents(folder);
}
}
finally
{
Marshal.ReleaseComObject(folder);
folder = null;
}
}
}
private void HookupCalendarEvents(MAPIFolder aCalendarFolder)
{
if (aCalendarFolder.DefaultItemType != OlItemType.olAppointmentItem)
{
throw new ArgumentException("The MAPIFolder must use " +
"AppointmentItems as the default type.");
}
//
// Ignore other user's calendars.
//
if ((m_folderPaths.Contains(aCalendarFolder.FolderPath) == false)
&& (IsUsersCalendar(aCalendarFolder)))
{
Items items = aCalendarFolder.Items;
//
// Store folder path to prevent double ups on our listeners.
//
m_folderPaths.Add(aCalendarFolder.FolderPath);
//
// Store a reference to the folder and to the items collection so that it remains alive for
// as long as we want. This keeps the ref count up on the underlying COM object and prevents
// it from being intermittently released (then the events don't get fired).
//
m_calendarFolders.Add(aCalendarFolder);
m_calendarItems.Add(items);
//
// Add listeners for the events we need.
//
((MAPIFolderEvents_12_Event)aCalendarFolder).BeforeItemMove +=
new MAPIFolderEvents_12_BeforeItemMoveEventHandler(Calendar_BeforeItemMove);
items.ItemChange += new ItemsEvents_ItemChangeEventHandler(CalendarItems_ItemChange);
items.ItemAdd += new ItemsEvents_ItemAddEventHandler(CalendarItems_ItemAdd);
}
}
private void CalendarItems_ItemAdd(object anItem)
{
AppointmentItem appointment = (anItem as AppointmentItem);
if (appointment != null)
{
try
{
if (this.AppointmentAdded != null)
{
this.AppointmentAdded(this, new EventArgs<AppointmentItem>(appointment));
}
}
finally
{
Marshal.ReleaseComObject(appointment);
appointment = null;
}
}
}
private void CalendarItems_ItemChange(object anItem)
{
AppointmentItem appointment = (anItem as AppointmentItem);
if (appointment != null)
{
try
{
if (this.AppointmentModified != null)
{
this.AppointmentModified(this, new EventArgs<AppointmentItem>(appointment));
}
}
finally
{
Marshal.ReleaseComObject(appointment);
appointment = null;
}
}
}
private void Calendar_BeforeItemMove(object anItem, MAPIFolder aMoveToFolder, ref bool Cancel)
{
if ((aMoveToFolder == null) || (IsDeletedItemsFolder(aMoveToFolder)))
{
AppointmentItem appointment = (anItem as AppointmentItem);
if (appointment != null)
{
try
{
if (this.AppointmentDeleting != null)
{
//
// Listeners to the AppointmentDeleting event can cancel the move operation if moving
// to the deleted items folder.
//
CancelEventArgs<AppointmentItem> args = new CancelEventArgs<AppointmentItem>(appointment);
this.AppointmentDeleting(this, args);
Cancel = args.Cancel;
}
}
finally
{
Marshal.ReleaseComObject(appointment);
appointment = null;
}
}
}
}
private bool IsUsersCalendar(MAPIFolder aFolder)
{
return (aFolder.Store != null);
}
private bool IsDeletedItemsFolder(MAPIFolder aFolder)
{
return (aFolder.EntryID == m_deletedItemsFolder.EntryID);
}
}
enter code here
I have an VSTO add in that is intercepting custom events. I have event handlers. I am looking for Add, Edit and Delete Items on the default calendar folder in outlook.
I have a button for creating custom appointments and after that is pressed the event handlers work fine but I need the event handlers to function from start up to catch custom events created in the previous session and they are not always firing at start up.
Here is some example code.
public partial class ThisAddIn
{
public string subjectName;
public Outlook.AppointmentItem apptItem;
public Outlook.Folder calendarFolder;
Outlook.Items items;
bool m_IsFirstTime = false;
CalendarMonitor calendarMonitor;
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
calendarMonitor = new CalendarMonitor(Application.ActiveExplorer());
calendarMonitor.AppointmentAdded += new EventHandler<EventArgs<AppointmentItem>>(Monitor_AppointmentAdded);
calendarMonitor.AppointmentModified += new EventHandler<EventArgs<AppointmentItem>>(Monitor_AppointmentModified);
calendarMonitor.AppointmentDeleting += new EventHandler<CancelEventArgs<AppointmentItem>>(Monitor_AppointmentDeleting);
Application.Inspectors.NewInspector += Inspectors_NewInspector;
Outlook.NameSpace ns = Application.Session;
calendarFolder = ns.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderCalendar) as Outlook.Folder;
items = calendarFolder.Items;
items.ItemChange += new Microsoft.Office.Interop.Outlook.ItemsEvents_ItemChangeEventHandler(Items_ItemChange);
}
}
//Calendar Monitor class
public class CalendarMonitor
{
private Explorer m_explorer;
private List<string> m_folderPaths;
private List<MAPIFolder> m_calendarFolders;
private List<Items> m_calendarItems;
private MAPIFolder m_deletedItemsFolder;
public event EventHandler<EventArgs<AppointmentItem>> AppointmentAdded;
public event EventHandler<EventArgs<AppointmentItem>> AppointmentModified;
public event EventHandler<CancelEventArgs<AppointmentItem>> AppointmentDeleting;
public CalendarMonitor(Explorer anExplorer)
{
m_folderPaths = new List<string>();
m_calendarFolders = new List<MAPIFolder>();
m_calendarItems = new List<Items>();
m_explorer = anExplorer;
m_explorer.BeforeFolderSwitch +=
new ExplorerEvents_10_BeforeFolderSwitchEventHandler(Explorer_BeforeFolderSwitch);
NameSpace session = m_explorer.Session;
try
{
m_deletedItemsFolder = session.GetDefaultFolder(OlDefaultFolders.olFolderDeletedItems);
HookupDefaultCalendarEvents(session);
}
finally
{
Marshal.ReleaseComObject(session);
session = null;
}
}
private void HookupDefaultCalendarEvents(NameSpace aSession)
{
MAPIFolder folder = aSession.GetDefaultFolder(OlDefaultFolders.olFolderCalendar);
if (folder != null)
{
try
{
HookupCalendarEvents(folder);
}
finally
{
Marshal.ReleaseComObject(folder);
folder = null;
}
}
}
private void Explorer_BeforeFolderSwitch(object aNewFolder, ref bool Cancel)
{
MAPIFolder folder = (aNewFolder as MAPIFolder);
//
// Hookup events to any other Calendar folder opened.
//
if (folder != null)
{
try
{
if (folder.DefaultItemType == OlItemType.olAppointmentItem)
{
HookupCalendarEvents(folder);
}
}
finally
{
Marshal.ReleaseComObject(folder);
folder = null;
}
}
}
private void HookupCalendarEvents(MAPIFolder aCalendarFolder)
{
if (aCalendarFolder.DefaultItemType != OlItemType.olAppointmentItem)
{
throw new ArgumentException("The MAPIFolder must use " +
"AppointmentItems as the default type.");
}
//
// Ignore other user's calendars.
//
if ((m_folderPaths.Contains(aCalendarFolder.FolderPath) == false)
&& (IsUsersCalendar(aCalendarFolder)))
{
Items items = aCalendarFolder.Items;
//
// Store folder path to prevent double ups on our listeners.
//
m_folderPaths.Add(aCalendarFolder.FolderPath);
//
// Store a reference to the folder and to the items collection so that it remains alive for
// as long as we want. This keeps the ref count up on the underlying COM object and prevents
// it from being intermittently released (then the events don't get fired).
//
m_calendarFolders.Add(aCalendarFolder);
m_calendarItems.Add(items);
//
// Add listeners for the events we need.
//
((MAPIFolderEvents_12_Event)aCalendarFolder).BeforeItemMove +=
new MAPIFolderEvents_12_BeforeItemMoveEventHandler(Calendar_BeforeItemMove);
items.ItemChange += new ItemsEvents_ItemChangeEventHandler(CalendarItems_ItemChange);
items.ItemAdd += new ItemsEvents_ItemAddEventHandler(CalendarItems_ItemAdd);
}
}
private void CalendarItems_ItemAdd(object anItem)
{
AppointmentItem appointment = (anItem as AppointmentItem);
if (appointment != null)
{
try
{
if (this.AppointmentAdded != null)
{
this.AppointmentAdded(this, new EventArgs<AppointmentItem>(appointment));
}
}
finally
{
Marshal.ReleaseComObject(appointment);
appointment = null;
}
}
}
private void CalendarItems_ItemChange(object anItem)
{
AppointmentItem appointment = (anItem as AppointmentItem);
if (appointment != null)
{
try
{
if (this.AppointmentModified != null)
{
this.AppointmentModified(this, new EventArgs<AppointmentItem>(appointment));
}
}
finally
{
Marshal.ReleaseComObject(appointment);
appointment = null;
}
}
}
private void Calendar_BeforeItemMove(object anItem, MAPIFolder aMoveToFolder, ref bool Cancel)
{
if ((aMoveToFolder == null) || (IsDeletedItemsFolder(aMoveToFolder)))
{
AppointmentItem appointment = (anItem as AppointmentItem);
if (appointment != null)
{
try
{
if (this.AppointmentDeleting != null)
{
//
// Listeners to the AppointmentDeleting event can cancel the move operation if moving
// to the deleted items folder.
//
CancelEventArgs<AppointmentItem> args = new CancelEventArgs<AppointmentItem>(appointment);
this.AppointmentDeleting(this, args);
Cancel = args.Cancel;
}
}
finally
{
Marshal.ReleaseComObject(appointment);
appointment = null;
}
}
}
}
private bool IsUsersCalendar(MAPIFolder aFolder)
{
return (aFolder.Store != null);
}
private bool IsDeletedItemsFolder(MAPIFolder aFolder)
{
return (aFolder.EntryID == m_deletedItemsFolder.EntryID);
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如果您希望正确触发事件,则需要保持源对象处于活动状态:
相反,请在类级别声明
Inspectors
实例:在类级别定义对象 (
Inspectors
)类级别以防止其被垃圾收集器清除。您可能会发现为检查器实现包装器并跟踪每个检查器中的项目级事件文章很有帮助。
例如,以下代码是解释可能问题的一个很好的示例:
Items
对象是在方法内部定义的,因此当 GC 触发时,可以从堆中清除该对象(如果方法完成其工作)。因此,此后您将永远不会触发事件。为了防止这种情况发生,您需要在类级别声明源对象:You need to keep the source objects alive if you want to get events fired correctly:
Instead, declare the
Inspectors
instance at the class level:Define the object (
Inspectors
) at the class level to prevent it from swiping by the garbage collector.You may find the Implement a wrapper for inspectors and track item-level events in each inspector article helpful.
For example, the following code is a good sample to explain a possible issue:
The
Items
object is defined inside the method, so when the GC triggers the object can be swiped from the heap (if method finished its work). So, you will never get events fired after that. To prevent this from happening you need to declare the source object at the class level: