虽然我在SO上发现了这个问题的很多实例,但我没有实现的解决方案已经解决了我的问题;希望你能帮我解决这个谜题。 注意:这是我第一次进入COM对象的世界,所以我的无知如此广泛。Outlook加载项::与其底层RCW分离的COM对象不能使用
作为一个开始,我使用阿德里安布朗的Outlook Add-In code。我不会完全复制他的CalendarMonitor
类;以下是相关部分:
public class CalendarMonitor
{
private ItemsEvents_ItemAddEventHandler itemAddEventHandler;
public event EventHandler<EventArgs<AppointmentItem>> AppointmentAdded = delegate { };
public CalendarMonitor(Explorer explorer)
{
_calendarItems = new List<Items>();
HookupDefaultCalendarEvents(session);
}
private void HookupDefaultCalendarEvents(_NameSpace session)
{
var folder = session.GetDefaultFolder(OlDefaultFolders.olFolderCalendar);
if (folder == null) return;
try
{
HookupCalendarEvents(folder);
}
finally
{
Marshal.ReleaseComObject(folder);
folder = null;
}
}
private void HookupCalendarEvents(MAPIFolder calendarFolder)
{
var items = calendarFolder.Items;
_calendarItems.Add(items);
// Add listeners
itemAddEventHandler = new ItemsEvents_ItemAddEventHandler(CalendarItems_ItemAdd);
items.ItemAdd += itemAddEventHandler;
}
private void CalendarItems_ItemAdd(object obj)
{
var appointment = (obj as AppointmentItem);
if (appointment == null) return;
try
{
AppointmentAdded(this, new EventArgs<AppointmentItem>(appointment));
}
finally
{
Marshal.ReleaseComObject(appointment);
appointment = null;
}
}
与添加约会无关的位已被编辑。
我实例化CalendarMonitor
上课的时候我阀芯了外接,和做的工作在AppointmentAdded事件,包括添加UserProperty到AppointmentItem:
private void ThisAddIn_Startup(object sender, EventArgs e)
{
_calendarMonitor = new CalendarMonitor(Application.ActiveExplorer());
_calendarMonitor.AppointmentAdded += monitor_AppointmentAdded;
}
private async void monitor_AppointmentAdded(object sender, EventArgs<AppointmentItem> e)
{
var item = e.Value;
Debug.Print("Outlook Appointment Added: {0}", item.GlobalAppointmentID);
try
{
var result = await GCalUtils.AddEventAsync(item);
//store a reference to the GCal Event for later.
AddUserProperty(item, Resources.GCalId, result.Id);
Debug.Print("GCal Appointment Added: {0}", result.Id);
}
catch (GoogleApiException ex)
{
PrintToDebug(ex);
}
finally
{
Marshal.ReleaseComObject(item);
item = null;
}
}
错误在这里抛出,在那里我尝试将一个UserProperty添加到AppointmentItem。我跟了我能找到的最好例子:
private void AddUserProperty(AppointmentItem item, string propertyName, object value)
{
UserProperties userProperties = null;
UserProperty userProperty = null;
try
{
userProperties = item.UserProperties;
userProperty = userProperties.Add(propertyName, OlUserPropertyType.olText);
userProperty.Value = value;
item.Save();
}
catch (Exception ex)
{
Debug.Print("Error setting User Properties:");
PrintToDebug(ex);
}
finally
{
if (userProperty != null) Marshal.ReleaseComObject(userProperty);
if (userProperties != null) Marshal.ReleaseComObject(userProperties);
userProperty = null;
userProperties = null;
}
}
...但它扼流圈,当我试图将UserProperty添加到AppointmentItem。我得到了一个非常流行的错误:COM object that has been separated from its underlying RCW cannot be used.
诚实地说,我不知道我在做什么;所以我拼命向我的Padawan寻找绝地大师。
Marshal.ReleaseComObject()是非常难看的手动内存管理。 C程序员必须编写并永远错误的那种。垃圾收集是为了防止这种错误一直发生而发明的。这里的情况大致相同,您将其称为未创建的对象。代码在不知情的情况下会继续使用被破坏的对象kaboom。停止帮助。了解垃圾收集器如何工作并学会信任它,[阅读本文](http://stackoverflow.com/a/17131389/17034)。 –
'处理定期预约项目时,应先释放任何事前参考,在访问或修改项目前获取定期预约项目的新参考,并在完成并保存更改后立即发布这些参考。这种做法适用于定期的AppointmentItem对象,以及任何Exception或RecurrencePattern对象。“ - 只是试图遵循该指导。相信我..所有这些'Marshal.ReleaseComObject()'东西都不是选择。 –
@HansPassant - 我读过你非常优秀的文章,但我仍然有点模糊。你可以从上面选择一种方法,并将其正确地重写为答案? –