0

Word 文書からテキストと画像を読み取って閉じようとしています。問題は、Word で問題が発生したり、複数の WINWORD.exe インスタンスを作成したりせずに、Word を閉じようとすることです。私の問題は、 を呼び出すMarshal.FinalReleaseComObject(app);と、Word.ApplicationClassWindows によって提供される一般的な例外 (「Word が動作を停止しました」) が発生することです。Excel 相互運用オブジェクトを適切にクリーンアップするにはどうすればよいですか?の解決策の多くを読みました。推奨事項を実装しましたが、まだ問題があります。

これが私のコードです。1 ページの Word ファイルを 1 つだけ読み込んでいます (例外が発生する "// Cleanup:" までスキップしてもかまいません)。

    private byte[] GetDocumentText(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.ApplicationClass app = new Word.ApplicationClass();
        Word.Documents docs = app.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);
                        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);
        Marshal.FinalReleaseComObject(doc);
        Marshal.FinalReleaseComObject(docs);
        (app as Word._Application).Quit(x, x, x);
        Marshal.FinalReleaseComObject(app); // Word encounters exception here.

        doc = null;
        docs = null;
        app = null;
        GC.Collect();
        GC.WaitForPendingFinalizers();
        GC.Collect();
        GC.WaitForPendingFinalizers();

        try { File.Delete(tmpPath); }
        catch { }

        return wordDoc;
    }

これは、ファイルを初めて読んだときに常に発生するとは限りません。2回目または3回目に読むと、通常エラーが発生します。

エラーが表示されないようにする方法はありますか?

4

3 に答える 3

0

を使用しないでください。これは、(.NET で) 唯一のリファラーであることがわかっているFinalReleaseComObjectRCW を解放/削除するためのハンマーです。

この場合、持っている参照からだけでなく、各 RCW、docdocsおよびの参照カウントを完全に減らしappます。

代わりに試してみてくださいReleaseComObject。ただし、Word のコレクションの 1 つから解放しようとしているオブジェクトの 1 つに接続されている .NET 列挙子がまだ有効で、使用中である場合は、これも同様に悪いことに注意してください。

ドキュメントを閉じ、Word を終了し、変数を に設定してnull、GC を実行するだけで十分です。コンパイラによっては、スタックから変数を破棄し、それらを に設定するコードを削除する場合がありますnull

于 2013-10-18T10:38:09.447 に答える
0

FinalReleaseComObject を呼び出す前に、 IsObjectValidかどうかを確認してみてください。

于 2013-10-17T22:38:53.630 に答える