Outlook加载项崩溃或您的服务器管理员限制了您可以同时打开的项目数 [英] Outlook Add-In Crashes or Your server administrator has limited the number of items you can open simultaneously

查看:176
本文介绍了Outlook加载项崩溃或您的服务器管理员限制了您可以同时打开的项目数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have created a simple Outlook Add-in for copying contacts from one folder to another.(~5000 contacts)

为什么我需要这个?如

Why I need this? There is a weird way for creating a public address book as described here.

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

So why not copy all the contacts in the public folder? I want my team to have a shared addressbook with my contacts but with only Fullname and emails as information.

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

I have added a toolbar with two Buttons. Choose folders and Synchronize.

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

My Problem is that when running Synchronization after a while I get

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

Your server administrator has limited the number of items you can open simultaneously. Try closing messages you have opened or removing attachments and images from unsent messages you are composing.

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

I used Marshal.ReleaseComObject in every Object, tried to add some delay between Add. But still get the same error.

然后,我在StackOverflow的此处找到了一条帖子,说要添加GC.Collect可以停止上面的错误,但Outlook总是在同步结束时崩溃,有时甚至在中间.

Then I found a post here in StackOverflow saying to add GC.Collect that stopped the error above but the Outlook always crashes at the end of Synchronizing and sometimes at the middle of it.

任何帮助将不胜感激.

同步代码

 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);
            }
        });
    }

推荐答案

请勿对Outlook集合使用任何LINQ语句.否则您将陷入这种情况.例如:

Do not use any LINQ statements against Outlook collections. Or you will trap into such situations. For example:

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

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

The line of code creates a new COM object for each item in the folder simultaneously. Instead, you can iterate over all items in the folder in the for loop and release objects instantly by using the Marshal.ReleaseComObject method.

 for (int i = 0; i < items.Count; i++)
 {
     object item = items[i];
     ...
     Marshal.ReleaseComObject(item); item = null;
 }

使用 System.Runtime.InteropServices.Marshal .ReleaseComObject 用于在使用完Outlook对象后将其释放.如果您的加载项尝试枚举Microsoft Exchange Server上存储的集合中的256个以上Outlook项目,则这一点尤其重要.如果不及时释放这些对象,则可以达到Exchange对任意一次打开的最大项目数施加的限制.然后在Visual Basic中将变量设置为Nothing(在C#中为null)以释放对该对象的引用.在系统地发布对象文章.

Use System.Runtime.InteropServices.Marshal.ReleaseComObject to release an Outlook object when you have finished using it. This is particularly important if your add-in attempts to enumerate more than 256 Outlook items in a collection that is stored on a Microsoft Exchange Server. If you do not release these objects in a timely manner, you can reach the limit imposed by Exchange on the maximum number of items opened at any one time. Then set a variable to Nothing in Visual Basic (null in C#) to release the reference to the object. Read more about that in the Systematically Releasing Objects article.

这篇关于Outlook加载项崩溃或您的服务器管理员限制了您可以同时打开的项目数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆