1

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 です)

さらに、1 つのファイル (つまり、ループ内の 1 つのファイル) のみを処理する場合、そのループ 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);
        }
    }

このエラーを修正または防止する方法はありますか? この文書オブジェクトの管理方法を改善するにはどうすればよいですか?

4

1 に答える 1

0

キーは 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();
    }
于 2013-10-21T21:19:01.100 に答える