Я работаю над старой надстройкой Outlook, которая, похоже, не срабатывает при событии ItemAdd.
Это код прямо сейчас:
public partial class MyAddin
{
private MAPIFolder sentItemsFolder;
private void InternalStartup()
{
this.Startup += this.MyAddinStartup;
this.Shutdown += this.MyAddinShutdown;
}
private void InboxFolderItemAdded(object item)
{
// Code that doesn't get executed
}
private void MyAddinShutdown(object sender, EventArgs e)
{
this.sentItemsFolder.Items.ItemAdd -= this.InboxFolderItemAdded;
this.sentItemsFolder.ReleaseComObject();
this.sentItemsFolder = null;
}
private void MyAddinStartup(object sender, EventArgs e)
{
using (var ns = this.Application.GetNamespace("MAPI").WithComCleanup())
{
this.sentItemsFolder = ns.Resource.GetDefaultFolder(OlDefaultFolder.oldFolderSentMail);
this.sentItemsFolder.Items.ItemAdd += this.InboxFolderItemAdded;
}
}
}
При размещении точки останова в InboxFolderItemAdded()
точка останова никогда не достигается. Я зашел достаточно далеко, чтобы заявить, что существует какая-то несовместимость с другой надстройкой, поскольку код работает, когда эта надстройка отключена. Проблема сейчас в том, что я недостаточно знаю, чтобы решить, в чем может быть проблема, можно ли каким-либо образом пометить объект SentItemsFolder
как общий? В случае, если другая надстройка пытается получить эксклюзивный доступ (на самом деле не знаю, как это работает). У меня нет исходного кода надстройки, которая нарушает код.
Я предполагаю, что реальный вопрос заключается в следующем: как отлаживать проблемы несовместимости с другими надстройками или есть ли способ отредактировать код, который мне нужно обойти?
this.sentItemsFolder.Items.ItemAdd -= this.InboxFolderItemAdded;
Определите исходный объект на уровне класса:
Outlook.Items items = null;
Затем в методе вы можете настроить его и подписаться на событие (я):
items = this.sentItemsFolder.Items;
items.ItemAdd -= this.InboxFolderItemAdded;
Итак, в основном вам нужно объявить исходный объект Items
на уровне класса, чтобы предотвратить его считывание сборщиком мусора.
То же самое относится к циклу, в котором вы подписываетесь на события Items
:
private void MyAddinStartup(object sender, EventArgs e)
{
using (var ns = this.Application.GetNamespace("MAPI").WithComCleanup())
{
this.sentItemsFolder = ns.Resource.GetDefaultFolder(OlDefaultFolder.oldFolderSentMail);
this.sentItemsFolder.Items.ItemAdd += this.InboxFolderItemAdded;
}
}
Вы можете определить список объектов Outlook.Items
, где вы можете хранить исходные объекты:
List<Outlook.Items> items = new List<Outlook.Items>();
private void MyAddinStartup(object sender, EventArgs e)
{
using (var ns = this.Application.GetNamespace("MAPI").WithComCleanup())
{
this.sentItemsFolder = ns.Resource.GetDefaultFolder(OlDefaultFolder.oldFolderSentMail);
Outlook.Items itemsObject = this.sentItemsFolder.Items;
itemsObject.ItemAdd += this.InboxFolderItemAdded;
// add to the list to prevent GC from swiping it out
items.Add(itemsObject);
}
}
Это связано с тем, что свойство Items возвращает объект, который висит в памяти до тех пор, пока метод не будет выполнен. Когда это будет сделано, объект будет помечен для просмотра GC.
Это сработало! Я читал об объявлении на уровне класса, но думал, что уже сделал это с
MAPIFolder sentItemsFolder
. Не могли бы вы объяснить, почемуsentItemsFolder.Items
оказался в GC, хотяsentItemsFolder
объявлен на уровне класса?