【问题标题】:Outlook Add-In Crashes or Your server administrator has limited the number of items you can open simultaneouslyOutlook 加载项崩溃或您的服务器管理员限制了您可以同时打开的项目数
【发布时间】:2016-08-18 00:55:36
【问题描述】:

我创建了一个简单的 Outlook 插件,用于将联系人从一个文件夹复制到另一个文件夹。(约 5000 个联系人)

为什么我需要这个?如here 所述,有一种创建公共地址簿的奇怪方法。

那么为什么不复制公共文件夹中的所有联系人呢?我希望我的团队与我的联系人共享一个通讯录,但只有全名和电子邮件作为信息。

我添加了一个带有两个按钮的工具栏。选择文件夹并同步。

我的问题是一段时间后运行同步时我得到了

您的服务器管理员限制了您可以同时打开的项目数量。尝试关闭您已打开的邮件或从您正在撰写的未发送邮件中删除附件和图像。

我在每个对象中都使用了Marshal.ReleaseComObject,试图在添加之间添加一些延迟。但仍然得到同样的错误。

然后我在 StackOverflow 中发现了一篇帖子,说要添加 GC.Collect 以停止上述错误,但 Outlook 在同步结束时总是崩溃,有时在同步过程中。

任何帮助将不胜感激。

同步代码

 private Task SynchronizeContactsSync()
    {
        return Task.Run(async () =>
        {
            if (!synchronizing)
            {
                synchronizing = true;

                Outlook.Folder toFolder = null;
                Outlook.Folder fromFolder = null;
                try
                {
                    if (!string.IsNullOrWhiteSpace(tEntryID) && !string.IsNullOrWhiteSpace(tStoreID) &&
                    !string.IsNullOrWhiteSpace(fStoreID) && !string.IsNullOrWhiteSpace(tEntryID))
                    {
                        toFolder = Application.Session.GetFolderFromID(tEntryID, tStoreID) as Outlook.Folder;
                        fromFolder = Application.Session.GetFolderFromID(fEntryID, fStoreID) as Outlook.Folder;
                    }

                    if (toFolder != null && fromFolder != null)
                    {
                        toFolder.InAppFolderSyncObject = false;
                        int currentItem = 0;


                        int itemCount = fromFolder.Items.Count;

                        //I dont want to use foreach because it keeps reference of each object until is done
                        //I cast it to list because i cant use for statement with fromFolder.Items

                        List<Outlook.ContactItem> items = fromFolder.Items.Cast<Outlook.ContactItem>().ToList(); ;

                        for (int i = 0; i < items.Count; i++)
                        {

                            //await Task.Delay(33);
                            await addContactSync(items[i], toFolder);
                            if (items[i] != null) Marshal.ReleaseComObject(items[i]);
                            GC.Collect();
                            GC.WaitForPendingFinalizers();
                            GC.Collect();
                            GC.WaitForPendingFinalizers();
                            currentItem++;
                            syncText = "Synchronize progress " + currentItem + " of " + itemCount;
                        }

                        synchronizing = false;
                        syncText = "No Synchronize in progress";



                    }
                    MessageBox.Show("Done.", "Synchronize", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    if (toFolder != null) Marshal.ReleaseComObject(toFolder);
                    if (fromFolder != null) Marshal.ReleaseComObject(fromFolder);
                    toFolder.InAppFolderSyncObject = true;
                }
                catch (Exception ex)
                {
                    if (toFolder != null) Marshal.ReleaseComObject(toFolder);
                    if (fromFolder != null) Marshal.ReleaseComObject(fromFolder);
                    toFolder.InAppFolderSyncObject = true;
                    synchronizing = false;
                    syncText = "No Synchronize in progress";
                    MessageBox.Show(ex.Message, "Synchronize", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }
            else
            {
                MessageBox.Show("Check you settings or please wait for the synchronization to finish.", "Synchronize", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        });
    }



    private Task addContactSync(Outlook.ContactItem item, Outlook.Folder toFolder)
    {
        return Task.Run(() =>
        {
            try
            {

                if (!string.IsNullOrWhiteSpace(item.Email1Address))
                {
                    string filter = "[FullName] = '" + item.FullName + "'";// "[NickName] = '" + item.NickName + "' or [Email1Address] = '" + item.Email1Address + "' or 

                    Outlook.ContactItem matches = (Outlook.ContactItem)toFolder.Items.Find(filter);
                    if (matches == null)
                    {
                        Outlook.ContactItem contact = toFolder.Items.Add(Outlook.OlItemType.olContactItem);
                        contact.FullName = item.FullName;
                        contact.NickName = item.NickName;
                        contact.Email1Address = item.Email1Address;
                        contact.Email2Address = item.Email2Address;
                        contact.Save();
                        Marshal.ReleaseComObject(contact);
                        itemSyncCount++;
                        lastItemSync = DateTime.Now;
                    }
                    else
                    {
                        matches.Email1Address = item.Email1Address;
                        matches.Email2Address = item.Email2Address;
                        matches.Save();
                        itemSyncCount++;
                        lastItemSync = DateTime.Now;
                    }

                    if (item != null) Marshal.ReleaseComObject(item);
                    if (matches != null) Marshal.ReleaseComObject(matches);

                }
            }
            catch (Exception ex)
            {
                Marshal.ReleaseComObject(item);
                MessageBox.Show(ex.Message, "Contact", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        });
    }

【问题讨论】:

    标签: c# outlook outlook-addin


    【解决方案1】:

    不要对 Outlook 集合使用任何 LINQ 语句。否则你会陷入这种情况。例如:

     List<Outlook.ContactItem> items = fromFolder.Items.Cast<Outlook.ContactItem>().ToList(); ;
    

    这行代码同时为文件夹中的每个项目创建一个新的 COM 对象。相反,您可以在 for 循环中遍历文件夹中的所有项目,并使用 Marshal.ReleaseComObject 方法立即释放对象。

     Outlook.Items items = fromFolder.Items;
     for (int i = 1; i <= items.Count; i++)
     {
         object item = items[i];
         Outlook.ContactItem contact = item as Outlook.ContactItem;
         if (contact != null) //can also have DistListItem objects
         {
             ...
             Marshal.ReleaseComObject(contact); contact = null;
         }
         Marshal.ReleaseComObject(item); item = null;
     }
    

    使用System.Runtime.InteropServices.Marshal.ReleaseComObject 在您使用完 Outlook 对象后释放它。如果您的加载项尝试枚举存储在 Microsoft Exchange Server 上的集合中超过 256 个 Outlook 项目,这一点尤其重要。如果您不及时释放这些对象,您可能会达到 Exchange 对每次打开的最大项目数的限制。然后在 Visual Basic 中将变量设置为 Nothing(在 C# 中为 null)以释放对对象的引用。在Systematically Releasing Objects 文章中了解更多信息。

    另请注意,.Net 中的 as 运算符会创建对必须释放的对象的额外引用。

    【讨论】:

    • 我做不到for (int i = 0; i &lt; fromFolder.Items.Count; i++) { fromFolder.Items[i] //Throws error } 另外请阅读所有问题。
    • 我能够通过使用 Eugene 的“Marshal.ReleaseComObject(item);”来避免错误具体来说,我将那行代码直接放在拉取 MailItem 属性的函数之后(即当我完成 MailItem 时)
    【解决方案2】:

    我会再次确认,上面的 Eugen 解决方案有效。我有一个不同的错误,因此我仍然收到 LIMIT 错误

    for (int i = 1; i <= 1000; i++)
    {
                MailItem item = items[i];
                if (item.ReceivedTime > np_start_time && item.ReceivedTime < np_end_time)
                {
                    String subject = item.Subject;
                    temp_msg.EmailFrom = item.SenderEmailAddress;
                    temp_msg.EmailSubjectLine = item.Subject;
                    temp_msg.EmailTimeStamp = item.ReceivedTime;
                    temp_msg.EmailBody = item.Body;
    
    
                    OL_messages.Add(temp_msg);
                    
                // Incorrect way - only objects in the if-clause are released
                // System.Runtime.InteropServices.Marshal.ReleaseComObject(item);
                // item = null;
    
                }
    
                // Correct - Place at the end of the loop
                System.Runtime.InteropServices.Marshal.ReleaseComObject(item);
                item = null; 
                
     }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多