简体   繁体   English

C#Outlook Addin调用的对象已与其客户端断开连接

[英]C# Outlook Addin The object invoked has disconnected from its clients

I'm doing a plugin for outlook, but when I try to get the namespaces for calendars, I get this error: http://i.stack.imgur.com/ZV6eN.png 我正在为Outlook做插件,但是当我尝试获取日历的命名空间时,出现此错误: http : //i.stack.imgur.com/ZV6eN.png

So, in some computers not happen, but when another person try to install this error its showed, my code that break the app is this: 因此,在某些计算机上没有发生,但是当其他人尝试安装此错误时,我的破坏应用程序的代码是:

private async void AddinModule_AddinInitialize(object sender, EventArgs e)
{        
        try
        {
            var app = this.OutlookApp;
            Outlook.NameSpace nameSpace = app.GetNamespace("MAPI");
            foreach (Outlook.Store store in nameSpace.Stores)
            {
                if (store.IsCachedExchange)
                {
                    calendarFolders.Add(store.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderCalendar));
                }
            }

            await updateAppItemList();
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message, "Error CODE 0x01", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
}


        private Task updateAppItemList()
        {
            appItems = new List<Outlook.AppointmentItem>();
            foreach (Outlook.MAPIFolder folder in calendarFolders)
            {
                Outlook.Items items = folder.Items;
                var parent = items.Parent as Outlook.MAPIFolder;
                if (!calendarItems.Any(x => (x.Parent as Outlook.MAPIFolder).StoreID == folder.StoreID))
                {
                    items.ItemAdd += this.ItemAdd;
                    items.ItemChange += this.ItemChange;

                    calendarItems.Add(items);
                }

                foreach (var item in items)
                {
                    Outlook.AppointmentItem appItem = item as Outlook.AppointmentItem;
                    if (appItem != null)
                    {
                        appItem.BeforeDelete += this.ItemRemove;
                        appItems.Add(appItem);
                    }
                }
            }
            return Task.FromResult(0);
        }

The Outlook Object Model(OOM) is not suited for multi-threading, specifically accessing the OOM in multiple threads. Outlook对象模型(OOM)不适合多线程,特别是在多个线程中访问OOM。

http://blogs.msdn.com/b/pcreehan/archive/2008/03/13/outlook-crashes-when-using-outlook-object-model-in-multiple-threads.aspx http://blogs.msdn.com/b/pcreehan/archive/2008/03/13/outlook-crashes-when-using-outlook-object-model-in-multiple-threads.aspx

Google search for "outlook multi thread issues" and check out. Google搜索“ outlook多线程问题”并签出。

The AddinInitialize event (from ADX) is not the right place for such calls. (来自ADX的) AddinInitialize事件不是进行此类调用的正确位置。 For example, if multiple profiles are configured in Outlook and the dialog for chosing the profile is shown, the event can be fired before the user chooses a particular profile. 例如,如果在Outlook中配置了多个配置文件,并显示了用于选择配置文件的对话框,则可以在用户选择特定配置文件之前触发该事件。 So, the namespace is not initialized yet. 因此,名称空间尚未初始化。 That's why I'd suggest using the AddinStartupComplete event handler instead. 这就是为什么我建议改用AddinStartupComplete事件处理程序的原因。

As for multithreading, Office applications use the single threaded apartment model (STA) and all calls made from another threads are marshalled to the main one (Outlook 2013 and later). 对于多线程,Office应用程序使用单线程单元模型(STA),并且从另一个线程进行的所有调用都将编组到主线程(Outlook 2013及更高版本)。 Moreover, previous Outlook versions may fire exceptions in such cases. 此外,在这种情况下,以前的Outlook版本可能会引发异常。 Use the main thread for dealing with the Outlook object model. 使用主线程处理Outlook对象模型。

As a workaround, you can use the low-level API (Extended MAPI) on which Outlook and other third-party components are based. 解决方法是,可以使用Outlook和其他第三方组件所基于的低级API(扩展MAPI)。 In that case you can run your low-level code on another thread. 在这种情况下,您可以在另一个线程上运行低级代码。

Finally, I've noticed that you don't release underlying COM objects instantly. 最后,我注意到您不会立即释放基础COM对象。 Use System.Runtime.InteropServices.Marshal.ReleaseComObject to release an Outlook object when you have finished using it. 使用完后,使用System.Runtime.InteropServices.Marshal.ReleaseComObject释放Outlook对象。 Then set a variable to Nothing in Visual Basic (null in C#) to release the reference to the object. 然后在Visual Basic中将变量设置为Nothing(在C#中为null)以释放对该对象的引用。 Read more about that in the Systematically Releasing Objects article. 在“ 系统发布对象”文章中了解有关此内容的更多信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM