我正在尝试编写一个应用程序,它将监视几个邮箱,并且在发现邮件时从每个项目中获取一些信息,然后一旦我列出了可以采取的项目动作。枚举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;
}
}
}
你是否从多个线程调用此代码? – 2010-01-27 00:45:38
对我来说,如果您使用Exchange 2007 API(作为Web服务启用)或简单的邮箱访问协议(如POP3或IMAP)(如果目标邮件服务器支持它),那么编码和资源需求会更轻松。我之前很轻松地使用了这两种方法,但是发现通过COM编程MS Office程序是最好的方法。但遗憾的是,我无法对这一点代码的具体问题发表太多评论...... – ewall 2010-01-27 00:52:51
@JP Alioto - 从单个线程调用代码,并且如果我删除对打开项目的方法的调用,则没有问题得到身体。 @ewall - 我会研究Exchange 07 API,但之前我没有使用它(或POP/IMAP),我觉得这个解决方案非常接近,我很想修复它:) – 2010-01-27 10:22:51