2010-01-27 55 views
1

我正在尝试编写一个应用程序,它将监视几个邮箱,并且在发现邮件时从每个项目中获取一些信息,然后一旦我列出了可以采取的项目动作。枚举C#中的Outlook项目时出现异常

但是无论我如何处理它,我都会触发Exchange执行255个RPC连接限制。

我对导致错误的原因绝对坚持 - 据我所见,我已经把一切都捆绑在一个方法中,并打电话给Marshal.ReleaseComObject ....我甚至接受性能打开和关闭Outlook应用程序自身。

任何建议,将大规模感激...(我似乎无法弄清楚,为什么我的代码看起来错在预览所以为了安全起见,我把它放在引擎收录太... 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; 
     } 
     } 

} 
+0

你是否从多个线程调用此代码? – 2010-01-27 00:45:38

+0

对我来说,如果您使用Exchange 2007 API(作为Web服务启用)或简单的邮箱访问协议(如POP3或IMAP)(如果目标邮件服务器支持它),那么编码和资源需求会更轻松。我之前很轻松地使用了这两种方法,但是发现通过COM编程MS Office程序是最好的方法。但遗憾的是,我无法对这一点代码的具体问题发表太多评论...... – ewall 2010-01-27 00:52:51

+0

@JP Alioto - 从单个线程调用代码,并且如果我删除对打开项目的方法的调用,则没有问题得到身体。 @ewall - 我会研究Exchange 07 API,但之前我没有使用它(或POP/IMAP),我觉得这个解决方案非常接近,我很想修复它:) – 2010-01-27 10:22:51

回答

1

我的要求与您的要求几乎相同。下面的示例应用程序是非常好的参考:

http://www.c-sharpcorner.com/UploadFile/rambab/OutlookIntegration10282006032802AM/OutlookIntegration.aspx

关于“交易所强制执行255 RPC连接限制”选中这些链接:
http://www.dimastr.com/Redemption/faq.htm
http://www.outlookcode.com/threads.aspx?forumid=2&messageid=26321

+0

This isn'这真的是答案,但最终我以赎罪去了。它大量简化了我的代码,最重要的是它的工作。 – 2010-02-09 13:22:25

0

不要创建每一个新的应用程序对象当你调用这个函数时,把它作为你的类的一个私有成员变量,直到你不再需要它为止。这样你只需要在你的构造函数中调用Namespace.Logon。

+0

@McAden - 我将应用程序和名称空间调用移到了方法中,希望关闭它们将允许系统正确释放COM对象。 如果我删除了对Item.Body的调用,应用程序将遍历所有5000多个项目,因此我确信问题在于如何释放对象 – 2010-01-27 10:26:58

+0

如果您使这些对象成为静态,您可以在这些对象上调用Marshal.ReleaseComObject ,在AppDomain.CurrentDomain.DomainUnload等事件处理程序中。 AppDomain肯定有这样的事件。 – 2013-02-06 20:19:14