在 C# 中枚举 Outlook 项目时出现异常

发布于 2024-08-19 15:21:07 字数 5751 浏览 1 评论 0原文

我正在尝试编写一个应用程序来监视几个邮箱,当发现邮件时,从每个项目中获取一些信息,然后一旦我有了项目列表,我就可以采取适当的操作。

但无论我如何处理它,我都会达到 Exchange 强制执行的 255 个 RPC 连接限制。

我完全不知道是什么导致了错误 - 据我所知,我已经将所有内容都绑定在一种方法中,并且正在调用 Marshal.ReleaseComObject....我什至接受打开和关闭的性能影响关闭 Outlook 应用程序句柄本身。

任何建议将不胜感激...(我似乎无法弄清楚为什么我的代码在预览中看起来是错误的,所以为了安全起见,我也将它放在了pastebin上... http://pastebin.com/m637eb95)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Office.Interop.Outlook;
using Microsoft.Office.Interop;
using System.Runtime.InteropServices;

namespace HandleMailingResponses
{
    class OutlookFolderTableScraper
    {
        public List<OutlookItem> GetItemsFromFolder(string folderName)
        {
            List<OutlookItem> returnList = new List<OutlookItem>();

            Application outlookHandle = new Application();
            NameSpace outlookNamespace = outlookHandle.GetNamespace("MAPI");
            Folders rootOutlookFolders = outlookNamespace.Folders;

            outlookNamespace.Logon(null, null, null, true);

            Folder requestedRoot = enumerateFolders(rootOutlookFolders, folderName);
            Folders theseFolders = requestedRoot.Folders;
            Folder thisInbox = enumerateFolders(theseFolders, "Inbox");

            Marshal.ReleaseComObject(requestedRoot);
            requestedRoot = null;
            Marshal.ReleaseComObject(rootOutlookFolders);
            rootOutlookFolders = null;

            string storeID = thisInbox.StoreID;

            Table thisTable = thisInbox.GetTable("",OlTableContents.olUserItems);

            //By default each item has the columns EntryID, Subject, CreationTime, LastModificationTime and MessageClass
            //we can add any of the other properties the MailItem or ReportItem object would have....
            Columns theseColumns = thisTable.Columns;
            theseColumns.Add("SenderEmailAddress");

            Marshal.ReleaseComObject(thisInbox);
            thisInbox = null;

            outlookNamespace.Logoff();
            Marshal.ReleaseComObject(outlookNamespace);
            outlookNamespace = null;
            outlookHandle.Quit();
            Marshal.ReleaseComObject(outlookHandle);
            outlookHandle = null;

            int count = 0;
            while (!thisTable.EndOfTable)
            {
                Row thisRow = thisTable.GetNextRow();
                object[] theseValues = (object[]) thisRow.GetValues();
                Console.WriteLine("processed {0}",count++);

                //get the body from this item
                string messageClass = (string)theseValues[4];
                string entryID = (string)theseValues[0];
                string body = getItemBody(entryID,storeID, messageClass);

                returnList.Add(new OutlookItem((string)theseValues[5], (string)theseValues[1], body, messageClass, entryID));
            }



            return returnList;
        }

        private string getItemBody(string entryID, string storeID, string messageClass)
        {
            Application outlookHandle = new Application();
            NameSpace outlookNamespace = outlookHandle.GetNamespace("MAPI");
            outlookNamespace.Logon(null, null, null, true);
            string body;

            if (messageClass.ToLower().StartsWith("report"))
            {
                ReportItem thisItem = (ReportItem)outlookNamespace.GetItemFromID(entryID, storeID);
                body = thisItem.Body;
                thisItem.Close(OlInspectorClose.olDiscard);
                //release this com reference
                int releaseResult;
                do
                {
                    releaseResult = Marshal.ReleaseComObject(thisItem);
                } while (releaseResult != 0);
            }
            else
            {
                MailItem thisItem = (MailItem)outlookNamespace.GetItemFromID(entryID, storeID);
                body = thisItem.Body;
                thisItem.Close(OlInspectorClose.olDiscard);
                //release this com reference
                int releaseResult;
                do
                {
                    releaseResult = Marshal.ReleaseComObject(thisItem);
                } while (releaseResult != 0);
            }

            outlookNamespace.Logoff();
            outlookNamespace = null;
            outlookHandle.Quit();
            outlookHandle = null;


            GC.Collect();
            GC.WaitForPendingFinalizers();

            return body;
        }

                    /// <summary>
        /// Iterates through an Outlook.Folders object searching for a folder with the given name
        /// </summary>
        /// <param name="rootFolder">An Outlook.Folder object</param>
        /// <param name="targetFolder"></param>
        /// <returns></returns>
        private Folder enumerateFolders(Folders rootFolders, string targetFolder)
        {
            Folder returnFolder = null;
            System.Collections.IEnumerator thisEnumerator = rootFolders.GetEnumerator();
            while (thisEnumerator.MoveNext())
            {
                Folder f = (Folder)thisEnumerator.Current;
                string name = f.Name;
                if (targetFolder.ToLower().Equals(name.ToLower()))
                {
                    returnFolder = f;
                    break;
                }
            }
            ICustomAdapter adapter = (ICustomAdapter)thisEnumerator;
            Marshal.ReleaseComObject(adapter.GetUnderlyingObject());
            adapter = null;
            return returnFolder;
        }
        }

}

I'm trying to write an app that will monitor a few mailboxes and when mail is found grab some info from each item and then once I have a list of the items I can take the appropriate actions.

But no matter how I approach it I'm hitting the Exchange enforced 255 RPC connections limit.

I'm absolutely stuck as to what is causing the error - as far as I can see I've got everything tied up in one method and am calling Marshal.ReleaseComObject.... I'm even accepting the performance hit of opening and closing the Outlook Application handle itself.

Any advice would be massively appreciated... (I can't seem to figure out why my code looks wrong in the preview so for safety's sake I've put it on pastebin too... http://pastebin.com/m637eb95)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Office.Interop.Outlook;
using Microsoft.Office.Interop;
using System.Runtime.InteropServices;

namespace HandleMailingResponses
{
    class OutlookFolderTableScraper
    {
        public List<OutlookItem> GetItemsFromFolder(string folderName)
        {
            List<OutlookItem> returnList = new List<OutlookItem>();

            Application outlookHandle = new Application();
            NameSpace outlookNamespace = outlookHandle.GetNamespace("MAPI");
            Folders rootOutlookFolders = outlookNamespace.Folders;

            outlookNamespace.Logon(null, null, null, true);

            Folder requestedRoot = enumerateFolders(rootOutlookFolders, folderName);
            Folders theseFolders = requestedRoot.Folders;
            Folder thisInbox = enumerateFolders(theseFolders, "Inbox");

            Marshal.ReleaseComObject(requestedRoot);
            requestedRoot = null;
            Marshal.ReleaseComObject(rootOutlookFolders);
            rootOutlookFolders = null;

            string storeID = thisInbox.StoreID;

            Table thisTable = thisInbox.GetTable("",OlTableContents.olUserItems);

            //By default each item has the columns EntryID, Subject, CreationTime, LastModificationTime and MessageClass
            //we can add any of the other properties the MailItem or ReportItem object would have....
            Columns theseColumns = thisTable.Columns;
            theseColumns.Add("SenderEmailAddress");

            Marshal.ReleaseComObject(thisInbox);
            thisInbox = null;

            outlookNamespace.Logoff();
            Marshal.ReleaseComObject(outlookNamespace);
            outlookNamespace = null;
            outlookHandle.Quit();
            Marshal.ReleaseComObject(outlookHandle);
            outlookHandle = null;

            int count = 0;
            while (!thisTable.EndOfTable)
            {
                Row thisRow = thisTable.GetNextRow();
                object[] theseValues = (object[]) thisRow.GetValues();
                Console.WriteLine("processed {0}",count++);

                //get the body from this item
                string messageClass = (string)theseValues[4];
                string entryID = (string)theseValues[0];
                string body = getItemBody(entryID,storeID, messageClass);

                returnList.Add(new OutlookItem((string)theseValues[5], (string)theseValues[1], body, messageClass, entryID));
            }



            return returnList;
        }

        private string getItemBody(string entryID, string storeID, string messageClass)
        {
            Application outlookHandle = new Application();
            NameSpace outlookNamespace = outlookHandle.GetNamespace("MAPI");
            outlookNamespace.Logon(null, null, null, true);
            string body;

            if (messageClass.ToLower().StartsWith("report"))
            {
                ReportItem thisItem = (ReportItem)outlookNamespace.GetItemFromID(entryID, storeID);
                body = thisItem.Body;
                thisItem.Close(OlInspectorClose.olDiscard);
                //release this com reference
                int releaseResult;
                do
                {
                    releaseResult = Marshal.ReleaseComObject(thisItem);
                } while (releaseResult != 0);
            }
            else
            {
                MailItem thisItem = (MailItem)outlookNamespace.GetItemFromID(entryID, storeID);
                body = thisItem.Body;
                thisItem.Close(OlInspectorClose.olDiscard);
                //release this com reference
                int releaseResult;
                do
                {
                    releaseResult = Marshal.ReleaseComObject(thisItem);
                } while (releaseResult != 0);
            }

            outlookNamespace.Logoff();
            outlookNamespace = null;
            outlookHandle.Quit();
            outlookHandle = null;


            GC.Collect();
            GC.WaitForPendingFinalizers();

            return body;
        }

                    /// <summary>
        /// Iterates through an Outlook.Folders object searching for a folder with the given name
        /// </summary>
        /// <param name="rootFolder">An Outlook.Folder object</param>
        /// <param name="targetFolder"></param>
        /// <returns></returns>
        private Folder enumerateFolders(Folders rootFolders, string targetFolder)
        {
            Folder returnFolder = null;
            System.Collections.IEnumerator thisEnumerator = rootFolders.GetEnumerator();
            while (thisEnumerator.MoveNext())
            {
                Folder f = (Folder)thisEnumerator.Current;
                string name = f.Name;
                if (targetFolder.ToLower().Equals(name.ToLower()))
                {
                    returnFolder = f;
                    break;
                }
            }
            ICustomAdapter adapter = (ICustomAdapter)thisEnumerator;
            Marshal.ReleaseComObject(adapter.GetUnderlyingObject());
            adapter = null;
            return returnFolder;
        }
        }

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

萌面超妹 2024-08-26 15:21:07

不要每次调用该函数时都创建一个新的 Application 对象,请将其保留为类的私有成员变量,直到不再需要它为止。这样您只需要在构造函数中调用 Namespace.Logon 即可。

Don't create a new Application object each time you call the function, keep it as a private member variable of your class until you no longer need it. That way you'll only need to call Namespace.Logon in your constructor.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文