簡體   English   中英

關閉Word文檔時RPC_E_SERVERFAULT

[英]RPC_E_SERVERFAULT when closing Word document

我正在嘗試循環讀取一組Word文件。 在循環的第一次迭代中,從來沒有問題。 在第2、3,.. n次迭代中,我收到以下錯誤,試圖關閉文檔:

The server threw an exception. (exception from hresult: 0x80010105 (rpc_e_serverfault))

我的電話如下:

(doc as Word._Document).Close(Word.WdSaveOptions.wdDoNotSaveChanges, x, x); (其中x是Type.Missing)

另外,當僅處理一個文件(即循環中的一個文件)時,在單獨運行該循環2、3等時,永遠不會引發錯誤。 第一次迭代后出現了一些中斷,但后續迭代中未解決。 但是,我似乎正確地重新初始化了所有變量,並且正在重用ApplicationClass對象。

我對此錯誤進行了一些體面的研究。 除了得知我們確實不應該使用COM Interop之外,我沒有發現太多。 一個StackOverflow的答案表明問題是多線程的,但是在我的代碼中似乎並不明顯。 盡管我90%確信這是一個錯誤。 我只是找不到。

我的代碼如下:我有一個類級別的變量,可以在循環的每次迭代中重復使用應用程序類: Word.ApplicationClass _WordApp;

循環在退出Word應用程序之前會運行以下代碼n次(讀取的文件數量一樣):

內部循環:

        byte[] wordDocBytes = GetWordDocumentData(att.Data, att.FileName);
        pagesToCombine.Add(wordDocBytes);
        if (counter == wordFileCount) { QuitWordApplication(); }
        else { counter += 1; }

GetWordDocumentData方法:

    private byte[] GetWordDocumentData(byte[] wordBytes, string path)
    {
        // Save bytes to word file in temp dir, open, copy info. Then delete the temp file after.

        object x = Type.Missing;
        string ext = Path.GetExtension(path).ToLower();
        string tmpPath = Path.ChangeExtension(Path.GetTempFileName(), ext);
        File.WriteAllBytes(tmpPath, wordBytes);

        // Open temp file with Excel Interop:
        Word.Documents docs = null;
        if (_WordApp == null)
        {
            _WordApp = new Word.ApplicationClass();
        }

        try
        {
            docs = _WordApp.Documents;
        }
        catch (COMException cx)
        {
            _WordApp = new Word.ApplicationClass();
            docs = _WordApp.Documents;
        }
        Word.Document doc = docs.Open(tmpPath, x, x, x, x, x, x, x, x, x, x, x, x, x, x);

        doc.ActiveWindow.Selection.WholeStory();
        doc.ActiveWindow.Selection.Copy();
        IDataObject data = Clipboard.GetDataObject();
        string documentText = data.GetData(DataFormats.Text).ToString();

        // Add text to pages.
        byte[] wordDoc = null;
        using (MemoryStream myMemoryStream = new MemoryStream())
        {
            Document myDocument = new Document();
            PdfWriter myPDFWriter = PdfWriter.GetInstance(myDocument, myMemoryStream); // REQUIRED.
            PdfPTable table = new PdfPTable(1);
            myDocument.Open();

            // Create a font that will accept unicode characters.
            BaseFont bfArial = BaseFont.CreateFont(@"C:\Windows\Fonts\Arial.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
            Font arial = new Font(bfArial, 12);

            // If Hebrew character found, change page direction of documentText.
            PdfPCell page = new PdfPCell(new Paragraph(documentText, arial)) { Colspan = 1 };
            Match rgx = Regex.Match(documentText, @"\p{IsArabic}|\p{IsHebrew}");
            if (rgx.Success) page.RunDirection = PdfWriter.RUN_DIRECTION_RTL;

            table.AddCell(page);

            // Add image to document (Not in order with text...)
            foreach (Word.InlineShape ils in doc.InlineShapes)
            {
                if (ils != null && ils.Type == Word.WdInlineShapeType.wdInlineShapePicture)
                {
                    PdfPCell imageCell = new PdfPCell();
                    ils.Select();
                    doc.ActiveWindow.Selection.Copy();
                    System.Drawing.Image img = Clipboard.GetImage();
                    byte[] imgb = null;
                    using (MemoryStream ms = new MemoryStream())
                    {
                        img.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg); // Null reference exception - SOMETIMES.
                        imgb = ms.ToArray();
                    }

                    Image wordPic = Image.GetInstance(imgb);
                    imageCell.AddElement(wordPic);
                    table.AddCell(imageCell);
                }
            }

            myDocument.Add(table);
            myDocument.Close();
            myPDFWriter.Close();
            wordDoc = myMemoryStream.ToArray();
        }

        // Cleanup:
        Clipboard.Clear();
        (doc as Word._Document).Close(Word.WdSaveOptions.wdDoNotSaveChanges, x, x); // "The server generated an exception." - SOMETIMES.
        try { File.Delete(tmpPath); }
        catch { }

        return wordDoc;
    }

QutiWordApplication方法:

    private void QuitWordApplication()
    {
        try
        {
            (_WordApp as Word._Application).Quit(Type.Missing, Type.Missing, Type.Missing);
            GC.Collect();
            GC.WaitForPendingFinalizers();
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message + ex.StackTrace);
        }
    }

有什么辦法可以解決或防止此錯誤? 如何改善管理此文檔對象的方式?

看來關鍵是Document.Activate():

doc.Activate();

應該在docs.Open(...)之后運行:

Word.Document doc = docs.Open(ref fpath, ref x, ref readOnly, ref x, ref x, ref x, ref x, ref x, ref x, ref x, ref x, ref visible, ref x, ref x, ref x, ref x);

我認為在Open()命令中使用ref x等也有幫助。 最后,我每次迭代都退出該應用程序。 現在不崩潰,並且WINWORD.exe進程不增加。 謝天謝地...

最終代碼:

    private byte[] GetWordDocumentData(byte[] wordBytes, string path) //
    {
        // Save bytes to word file in temp dir, open, copy info. Then delete the temp file after.

        object x = System.Reflection.Missing.Value;
        string ext = Path.GetExtension(path).ToLower();
        string tmpPath = Path.ChangeExtension(Path.GetTempFileName(), ext);
        File.WriteAllBytes(tmpPath, wordBytes);

        // Open temp file with Excel Interop:
        Word.Documents docs = null;
        Word.ApplicationClass app = new Word.ApplicationClass();

        try
        {
            docs = app.Documents;
        }
        catch
        {
            app = new Word.ApplicationClass();
            docs = app.Documents;
        }

        object fpath = tmpPath;
        object visible = false;
        object readOnly = false;
        Word.Document doc = docs.Open(ref fpath, ref x, ref readOnly, ref x, ref x, ref x, ref x, ref x, ref x, ref x, ref x, ref visible, ref x, ref x, ref x, ref x);
        doc.Activate(); //New
        doc.ActiveWindow.Selection.WholeStory();
        doc.ActiveWindow.Selection.Copy();
        IDataObject data = Clipboard.GetDataObject();
        string documentText = data.GetData(DataFormats.Text).ToString();

        // Add text to pages.
        byte[] wordDoc = null;
        using (MemoryStream myMemoryStream = new MemoryStream())
        {
            Document myDocument = new Document();
            PdfWriter myPDFWriter = PdfWriter.GetInstance(myDocument, myMemoryStream); // REQUIRED.
            PdfPTable table = new PdfPTable(1);
            myDocument.Open();

            // Create a font that will accept unicode characters.
            BaseFont bfArial = BaseFont.CreateFont(@"C:\Windows\Fonts\Arial.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
            Font arial = new Font(bfArial, 12);

            // If Hebrew character found, change page direction of documentText.
            PdfPCell page = new PdfPCell(new Paragraph(documentText, arial)) { Colspan = 1 };
            Match rgx = Regex.Match(documentText, @"\p{IsArabic}|\p{IsHebrew}");
            if (rgx.Success) page.RunDirection = PdfWriter.RUN_DIRECTION_RTL;

            table.AddCell(page);

            // Add image to document (Not in order with text...)
            foreach (Word.InlineShape ils in doc.InlineShapes)
            {
                if (ils != null && ils.Type == Word.WdInlineShapeType.wdInlineShapePicture)
                {
                    PdfPCell imageCell = new PdfPCell();
                    ils.Select();
                    doc.ActiveWindow.Selection.Copy();
                    System.Drawing.Image img = Clipboard.GetImage();
                    byte[] imgb = null;
                    using (MemoryStream ms = new MemoryStream())
                    {
                        img.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
                        imgb = ms.ToArray();
                    }

                    Image wordPic = Image.GetInstance(imgb);
                    imageCell.AddElement(wordPic);
                    table.AddCell(imageCell);
                }
            }

            myDocument.Add(table);
            myDocument.Close();
            myPDFWriter.Close();
            wordDoc = myMemoryStream.ToArray();
        }

        Cleanup(x, tmpPath, app, doc);

        return wordDoc;
    }

我認為將清理工作與工作分開很重要:

    private static void Cleanup(object x, string tmpPath, Word.ApplicationClass app, Word.Document doc)
    {
        Clipboard.Clear();
        object Save = false;
        (doc as Word._Document).Close(ref Save, ref x, ref x);
        doc = null;
        (app as Word._Application).Quit();
        app = null;
        try { File.Delete(tmpPath); }
        catch { }
        GC.Collect();
        GC.WaitForPendingFinalizers();
        GC.Collect();
        GC.WaitForPendingFinalizers();
    }

暫無
暫無

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

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