我正在尝试循环读取一组 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;
}
QutiWord应用方法:
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);
}
}
有什么办法可以修复或防止此错误?如何改进管理此文档对象的方式?