简体   繁体   English

将Outlook联系人导出到CSV时,“ RPC服务器不可用”

[英]“RPC Server is unavailable” when exporting Outlook contacts to CSV

I am exporting Outlook contacts with a custom form to CSV from a specific Contacts folder. 我正在将具有自定义表单的Outlook联系人从特定的Contacts文件夹导出为CSV。 This folder is not the default location. 此文件夹不是默认位置。 It is a large folder with almost 7,000 contacts. 这是一个包含近7,000个联系人的大文件夹。 This is a shared mailbox in Office 365, but we can't use the Outlook or Graph APIs because of the custom data. 这是Office 365中的共享邮箱,但是由于自定义数据,我们无法使用Outlook或Graph API。

My code below works fine, except that after iterating through 200-800 contacts, I get this error: "RPC Server is unavailable. (Exception from HRESULT: 0x800706BA)." 我的下面的代码工作正常,除了在遍历200-800个联系人之后,我收到此错误:“ RPC服务器不可用。(HRESULT的异常:0x800706BA)。”

I also tried exporting the folder to a .pst and accessing that folder on my local machine. 我还尝试将文件夹导出到.pst并访问本地计算机上的该文件夹。 The result is essentially the same. 结果基本相同。 UPDATE: I've been watching Outlook.exe in the task manager, and it steadily increases its memory consumption to around 300MB before crashing. 更新:我一直在任务管理器中观看Outlook.exe,它在崩溃前稳定地将其内存消耗增加到300MB左右。 I've tried the same code on a laptop running Office 2010, and I get an "Out of Memory" error. 我在运行Office 2010的笔记本电脑上尝试了相同的代码,但出现“内存不足”错误。

I get the error whether Outlook is open or closed, but closing Outlook during program operation will immediately trigger this error. 无论Outlook是打开还是关闭,我都会收到错误消息,但是在程序运行过程中关闭Outlook会立即触发此错误。 Outlook either starts (or restarts) following this error. Outlook会在出现此错误后启动(或重新启动)。 I've read a number of SO posts and articles related to this error, but I'm not sure exactly what's going on. 我已经阅读了许多与该错误有关的SO帖子和文章,但是我不确定到底是怎么回事。 Any help is appreciated. 任何帮助表示赞赏。

UPDATE: Code has been updated to use for loops instead of foreach loops per Dmitry Streblechenko's suggestion. 更新:根据Dmitry Streblechenko的建议,代码已更新为for循环,而不是foreach循环。

using System;
using Microsoft.Office.Interop.Outlook;
using System.Text;
using System.IO;
using System.Runtime.InteropServices;

namespace OutlookContacts
{
    class Program
    {
        static void Main(string[] args)
        {
            var encoding = Encoding.UTF8;
            string csvPath = @"myCSVPath";
            Application outlook = new Application();
            NameSpace ns = outlook.GetNamespace("MAPI");
            MAPIFolder sharedContacts;
            string recipientName = "myEmail@myDomain";
            StringBuilder headerRow = new StringBuilder();
            Recipient recip = ns.CreateRecipient(recipientName);
            StreamWriter writer = new StreamWriter(csvPath, false, encoding);

            recip.Resolve();
            if (recip.Resolved)
            {
                try
                {
                    //EntryID and StoreID of my folder
                    sharedContacts =
                        ns.GetFolderFromID(
                            "myEntryID",
                            "myStoreID"
                            );
                    Items contacts = sharedContacts.Items;

                    //Writing header row
                    ContactItem first = contacts.GetFirst();
                    var properties = first.ItemProperties;
                    for(int i = 0; i < properties.Count; i++)
                    {
                        try
                        {
                            headerRow.Append(string.Format("\"{0}\",", properties[i].Name));
                        }
                        catch (System.Exception ex)
                        {
                            headerRow.Append(string.Format("{0},", ex.Message));
                        }
                    }
                    headerRow.AppendLine(Environment.NewLine);
                    WriteToCSV(writer, headerRow);
                    Console.WriteLine("Header row written;");
                    Marshal.ReleaseComObject(properties);
                    Marshal.ReleaseComObject(first);

                    //Writing Records
                    for (int i = 1; i <= contacts.Count; i++)
                    {
                        object o = contacts[i];
                        if (o is ContactItem)
                        {
                            ContactItem contact = (ContactItem)o;
                            if (contact != null)
                            {
                                Console.Write(contact.FullName);
                                StringBuilder dataRow = new StringBuilder();
                                ItemProperties contactProps = contact.ItemProperties;
                                for (int j = 0; j < contactProps.Count; j++)
                                {
                                    ItemProperty property = contactProps[j];

                                    try
                                    {
                                        if (property.Value == null)
                                        {
                                            string value = "null,";
                                            dataRow.Append(value);
                                        }
                                        //else if (property.Name == "Attachments")
                                        //{
                                        //    //Attachment file names
                                        //    string attachment = "";
                                        //    for (int k = 1; k < contact.Attachments.Count; k++)  
                                        //    {
                                        //            attachment = (string.Format("\"{0}\"; ", contact.Attachments[k].FileName));
                                        //            dataRow.Append(attachment);
                                        //    }
                                        //    dataRow.Append(",");
                                        //}
                                        else
                                        {
                                            string value = property.Value.ToString();
                                            value = value.Replace("\r\n\r\n\r\n", "\r\n")
                                                .Replace("\r\n\r\n", "\r\n")
                                                .Replace("\"", "'");
                                            value = (string.Format("\"{0}\",", value));
                                            dataRow.Append(value);
                                        }
                                    }
                                    catch (System.Exception ex)
                                    {
                                        string value = string.Format("{0}: {1},", property.Name, ex.Message);
                                        dataRow.Append(value);
                                    }

                                    Marshal.ReleaseComObject(property);
                                }
                                dataRow.Append(Environment.NewLine);
                                WriteToCSV(writer, dataRow);
                                Marshal.ReleaseComObject(contactProps);
                                Marshal.ReleaseComObject(contact);
                            }
                            Marshal.ReleaseComObject(o);
                            counter++;
                            Console.WriteLine(": Written " + counter);
                        }
                    }
                }
                catch (System.Exception ex)
                {
                    Console.WriteLine(dataRow.ToString(), ex.Message);
                    Console.ReadKey();
                }

            }

        }

        static void WriteToCSV(StreamWriter writer, StringBuilder row)
        {
            var data = row.ToString();
            writer.WriteAsync(data);
        }

    }
}

Looks like you are running out of RPC channels. 看起来您用完了RPC通道。 You need to avoid using foreach loops (they tend to keep all collection members referenced until the loop exits) and explicitly release all COM objects are soon as you are done with them. 您需要避免使用foreach循环(它们倾向于保持引用所有集合成员,直到循环退出),并在完成处理后立即显式释放所有COM对象。

Off the top of my head: 从我的头顶上:

for(int i = 1; i <= contacts.Count; i++)
{
    obejct o = contacts[i];
    ContactItem contact = o as ContactItem;
    if (o != null)
    {
        ItemProperties properties = contact.ItemProperties;
        StringBuilder newLine = new StringBuilder();
        for (int j = 1; j <= properties.Count; j++)
        {
            ItemProperty property = properties[j];
            var value = "";
            if (property.Value == null)
            {
                value = "null,";
                Console.WriteLine(value);
                newLine.Append(value);
            }
            else
            {
                value =  property.Value.ToString() + ",";
                newLine.Append(value);
            }
            Marshal.ReleaseComObject(property);
        }
        newLine.Append(Environment.NewLine);
        WriteToCSV(writer, newLine);
        Marshal.ReleaseComObject(properties);
        Marshal.ReleaseComObject(contact);
    }
    Marshal.ReleaseComObject(o);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM