簡體   English   中英

Outlook 加載項崩潰或您的服務器管理員限制了您可以同時打開的項目數

[英]Outlook Add-In Crashes or Your server administrator has limited the number of items you can open simultaneously

我創建了一個簡單的 Outlook 插件,用於將聯系人從一個文件夾復制到另一個文件夾。(約 5000 個聯系人)

為什么我需要這個? 如此處所述,有一種創建公共地址簿奇怪方法。

那么為什么不復制公共文件夾中的所有聯系人呢? 我希望我的團隊與我的聯系人共享通訊錄,但只有全名和電子郵件作為信息。

我添加了一個帶有兩個按鈕的工具欄。 選擇文件夾和同步。

我的問題是,一段時間后運行同步時,我得到

您的服務器管理員限制了您可以同時打開的項目數量。 嘗試關閉您已打開的郵件或從您正在撰寫的未發送郵件中刪除附件和圖像。

我在每個對象中都使用了Marshal.ReleaseComObject ,試圖在 Add 之間添加一些延遲。 但仍然得到同樣的錯誤。

然后我在 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);
            }
        });
    }

不要對Outlook集合使用任何LINQ語句。 否則您將陷入這種情況。 例如:

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

代碼行同時為文件夾中的每個項目創建一個新的COM對象。 相反,您可以遍歷for循環中文件夾中的所有項目,並使用Marshal.ReleaseComObject方法立即釋放對象。

 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)以釋放對該對象的引用。 在“ 系統發布對象”文章中了解有關此內容的更多信息。

我會再次確認,上面的 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; 
            
 }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM