2013-10-18 5 views
1

루프의 Word 파일 그룹을 읽으려고합니다. 루프의 첫 번째 반복에서는 문제가 발생하지 않습니다. 2, 3 일 .. n 번째 반복, 나는 다음과 같은 오류 문서를 닫을 시도가 나타납니다Word 문서를 닫을 때 RPC_E_SERVERFAULT

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 상호 운용성을 사용해서는 안된다는 것을 배우면서, 나는별로 발견하지 못했습니다. 한 StackOverflow 대답 멀티 스레딩 문제를 제안했지만 내 코드에서 분명하지 않습니다; 나는 90 % 확실하지만 그것은 버그입니다. 나는 그것을 찾을 수 없었습니다. 다음과 같이

내 코드는 다음과 같습니다 내가 루프의 각 반복에 대한 응용 프로그램 클래스를 다시 사용하기위한 클래스 레벨의 변수가 있습니다 많은 파일로 ( Word.ApplicationClass _WordApp;

루프는 다음 코드를 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); 
     } 
    } 

어떤 식 으로든 내가이 오류를 수정하거나 방지 할 수 있습니까? 이 문서 객체를 관리하는 방법을 어떻게 향상시킬 수 있습니까? 내가 사용 생각

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);

: docs.Open (...) 한 후 실행해야합니다

doc.Activate();

:

+1

말씀이 추락했다. 그것은 * 왜 * 추락했는지, 인터롭 튜브를 통해 정보를 압축 할 수 없다는 것을 말하지 않습니다.왜 Word 자체에 집중해야 하는지를 알아야합니다. 그게 무엇인지 모르겠지만 먼저 Windows 응용 프로그램 이벤트 로그에서 이동 경로를 찾습니다. 다음으로, 나는 winword.exe에 디버거를 붙이고 Debug + Exceptions를 사용하여 더 많은 것을 알아 내기 위해 체크 박스를 던져 넣었다. 그런 다음 추가 기능을 사용하지 않도록 설정합니다. 다음으로 필자는 PDF 작성자가 cooties를 사용하지 못하게하고 옵션을 사용 중지하거나 팅커를 사용하면 어떻게 될지 알아 봅니다. –

+0

각 반복마다 응용 프로그램 개체를 만들려고 했습니까? 그 추락인가? –

+0

@HansPassant : 응용 프로그램 로그와 관련하여 금요일에 오류가있는 응용 프로그램 이름이 WINWORD.EXE이고 모듈 이름 VBE6.DLL이 잘못되었음을 알리는 'Classic'응용 프로그램 오류가 발생했습니다. 무슨 일이 있었는지는 정말로 말하지 않습니다. 위 코드가 실행 중입니다. Itextsharp 코드를 제거하면 오류 모듈은 이제 ntdll.dll이됩니다. 설명한대로 디버거를 어떻게 부착합니까? 나는 그것을 봤지만 어떻게하는지 알지 못했다. Claptrap : 아무런 도움없이 각 반복마다 ApplicationClass를 다시 만들려고했습니다. 첫 번째 또는 두 번째 반복에서 충돌이 발생합니다. – Paul

답변

0

이 키가 Document.Activate()이었다 보인다 ref x, 등 ... Open() 명령에서도 도움이되었습니다. 그리고 매 반복마다 애플리케이션을 종료했습니다. 이제는 충돌이 발생하지 않고 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(); 
    } 
관련 문제