RPC_E_SYS_CALL_FAILED Context disconnected

  • VB.NET
  • .NET (FX) 4.0

Es gibt 9 Antworten in diesem Thema. Der letzte Beitrag () ist von ErfinderDesRades.

    RPC_E_SYS_CALL_FAILED Context disconnected

    Hallo zusammen,

    mein Programm verabschiedet sich mit der Meldung "RPC_E_SYS_CALL_FAILED", wenn es zu lange läuft.

    Das Problem ist: Diese lange Laufzeit ist normal. Die Software öffnet Word und fügt aus verschiedenen Wordvorlagen den Inhalt in ein "Hauptdokument" ein.
    Kurz zum Ablauf: Ein Benutzer wählt in der Programmoberfläche aus, welche Daten das Dokument beinhalten soll. Es gibt aktuell 121 Einträge.
    Wähle ich so 60-70 aus, klappt das auch noch einwandfrei, bei allen ist die Laufzeit sehr lang und nach ca. 3 Minuten stürzt das Programm mit der angegebenen Meldung ab.

    Ich habe jetzt nachgelesen, dass es daran liegt, dass die COM-Objekte geschlossen werden, weil sie auf eine Antwort warten, aber eigentlich wird das Hauptdokument permanent beschrieben, also sollte die Verbindung ja offen bleiben. Die Vorlagen werden immer nur temporär geöffnet mit folgendem Code:

    Quellcode

    1. For i = 0 To (Modul_Global.analysen.Rows.Count - 1) Step 1
    2. AddProgressbarStep()
    3. Label2.Text = "Verarbeite: " & Modul_Global.analysen.Rows(i)("Dateiname")
    4. Dim wordtemp As New Microsoft.Office.Interop.Word.Application
    5. Dim doctemp As Microsoft.Office.Interop.Word.Document
    6. doctemp = wordtemp.Documents.Open(filepath & Modul_Global.analysen.Rows(i)("Dateiname"))
    7. doctemp.Activate()
    8. doctemp.Range.WholeStory()
    9. doctemp.Range.Copy()
    10. doc_gesamt.Activate()
    11. word.Selection.EndKey(Unit:=Microsoft.Office.Interop.Word.WdUnits.wdStory)
    12. word.Selection.WholeStory()
    13. word.Selection.NoProofing = True
    14. word.Selection.EndKey(Unit:=Microsoft.Office.Interop.Word.WdUnits.wdStory)
    15. word.Selection.PasteAndFormat(wordoptions.WdRecoveryType.wdFormatOriginalFormatting)
    16. If i < (Modul_Global.analysen.Rows.Count - 1) Then
    17. word.Selection.InsertBreak(Type:=Microsoft.Office.Interop.Word.WdBreakType.wdPageBreak)
    18. word.Selection.EndKey(Unit:=Microsoft.Office.Interop.Word.WdUnits.wdStory)
    19. Else
    20. word.Selection.GoTo(What:=wordoptions.WdGoToItem.wdGoToPage, Which:=1)
    21. End If
    22. doctemp.Close(False)
    23. wordtemp.Quit()
    24. System.Runtime.InteropServices.Marshal.FinalReleaseComObject(doctemp)
    25. Next


    Kurz zur Beschreibung des Codeschnipsels: Vorher wird natürlich Word schon gestartet und das Hauptdokument erstellt, für jede Datei, aus der kopiert werden soll, wird eine neue Instanz von word gestartet und auch wieder geschlossen.

    Ich bin kein VB-Profi, deshalb stehe ich ein bisschen ratlos da...
    Danke für die glorreiche Antwort. Die beiden Posts hatte ich schon gefunden und sie haben mir nicht geholfen. Wie ich schon sagte, ich bin kein Profi, arbeite mit VB.Net und nicht C# und weiß nicht, wie ich das übersetzte und würde es erst gerne verstehen, bevor ich es einbaue.
    Ich würde trotzdem den Fehler mal genauer verstehen, weil ich nicht genau weiß, warum und wie er zustande kommt und was genau diese Maßnahmen warum machen.
    Welchen Sinn hätte das Forum, wenn ich nur Codeschnipsel kopieren würde?

    Ich weiß du meinst es gut, aber verstehen geht für mich über "benutzen können".

    Broco schrieb:

    Die Vorlagen werden immer nur temporär geöffnet mit folgendem Code
    Zunächst: Dein Code schließt die COM-Objekte nicht sauber. Ein FinalReleaseComObject() am Ende reicht da nicht aus. Suche bitte hier im Forum nach anderen Beiträgen von mir zu diesem Thema - oft geht es dabei um Excel, aber das ist in diesem Fall egal. Du musst unbedingt deine Objekte vernünftig freigeben, sonst produzierst du ein MemoryLeak, an dem du bei einer dauerhaft laufenden Anwendung nach X Zeiteinheiten immer scheitern wirst.

    Broco schrieb:

    für jede Datei, aus der kopiert werden soll, wird eine neue Instanz von word gestartet und auch wieder geschlossen

    Das ist ein weiteres Problem: Du erzeugst zu viele Aufrufe an den COM-Server Word. Der macht Callbacks, die dein Code aber nicht bearbeitet (wegen der For-Schleife). Irgendwann ist die MessageQueue des aufrufenden Threads voll und es fliegt eine RPC_E_SYS_CALL_FAILED-Exception.

    Hier ist die ganze Geschichte dazu: blogs.msdn.com/b/carlos/archiv…tudy.aspx?Redirected=true

    Lösungsvorschläge gibt es dort auch: Implementiere IMessageFilter, wie in KidRicks Stackoverflow-Post verlinkt: blogs.msdn.com/b/andreww/archi…-in-an-office-add-in.aspx

    Anderer Vorschlag: Verwende einen eigenen Thread für die Word-Aufrufe. Achtung: Dann musst du eine MessageLoop für diesen Thread schreiben, sonst kassierst du wieder dieselbe Exception, nur viel schneller.
    Gruß
    hal2000
    Hast du vielleicht einen Link zu einem Beitrag? Ich bin jetzt nicht ganz so firm mit der Suche hier und du hast schon einige Beiträge zum Thema Excel verfasst.

    hal2000 schrieb:

    Das ist ein weiteres Problem: Du erzeugst zu viele Aufrufe an den COM-Server Word. Der macht Callbacks, die dein Code aber nicht bearbeitet (wegen der For-Schleife). Irgendwann ist die MessageQueue des aufrufenden Threads voll und es fliegt eine RPC_E_SYS_CALL_FAILED-Exception.

    Ich verstehe nicht so ganz. Ich habe ja eine Wordinstanz offen, die ja auch geöffnet bleiben muss, denn wie schreibe ich sonst in die geöffnete Datei?
    Und wie soll ich das sonst machen als mit der Schleife?

    Auch das mit dem eigenen Thread verstehe ich nicht so ganz, ich bin, wie gesagt, kein VB-Profi, normalerweise scripte ich nur.

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „Broco“ ()

    Broco schrieb:

    Hast du vielleicht einen Link zu einem Beitrag?
    Klar, such dir was aus:
    (Falls das Suchergebnis noch existiert): vb-paradise.de/index.php/SearchResult/81538/?highlight=Excel
    HRESULT Ausnahme in ComboBox - Behandeln?
    Excel Prozess nach Schreiben in Exceldatei beenden
    Excel Prozess nach Schreiben in Exceldatei beenden
    Offene Instanzen mit Microsoft.Office.Interop.Excel
    Excel.Application - Der RPC-Server ist nicht verfügbar
    Multithreading mit Threadpool - Warte auf letzten lesenden Thread

    Broco schrieb:

    Und wie soll ich das sonst machen als mit der Schleife?
    Nicht alle Dokumente direkt hintereinander, sondern einzeln, mit Pausen dazwischen. Wenn sich das Fenster zwischendurch aufhängt ("reagiert nicht"), hast du was falsch gemacht. Wenn das Fenster immer bedienbar bleibt, ist alles in Ordnung. Das bedeutet für dich, dass du einen anderen Thread mit eigener Nachrichtenschleife verwenden musst.

    Broco schrieb:

    Auch das mit dem eigenen Thread verstehe ich nicht so ganz, ich bin, wie gesagt, kein VB-Profi, normalerweise scripte ich nur.
    Das ist ein Problem, weil eine saubere Lösung hier sehr viel Hintergrundwissen erfordert. Leider ist diese Lösung erforderlich, um den Fehler zu beheben, der bei dir auftritt. Ich kann dir aber auch nicht dein Programm schreiben - dazu fehlt mir die Zeit. Du musst dich in die Themen "Threading" und "COM-Interop" einlesen, am besten direkt im MSDN. Sorry, aber es dauert schon mindestens ein Jahr, insbesondere letzteres nur im Ansatz zu verstehen (meine Erfahrung).

    Du sagtest einige Beiträge zuvor, dass du die Lösung verstehen (und nicht nur einbauen) möchtest - das wird aber dauern. Wenn du den IMessageFilter (s.o.) korrekt implementierst, ist dir schon viel geholfen, weil es einfach dein Problem löst (nicht ganz perfekt, aber es sollte funktionieren).
    Gruß
    hal2000
    Ich habs hinbekommen. Der Fehler war, dass ich 120 Office-Instanzen augemacht habe durch die Schleife. Ich habe jetzt statt "wordtemp" einfach meine ursprüngliche Instanz weiter genutzt. Das hat einwandfrei geklappt und jetzt läuft es durch.
    Marshal Release auch bei jedem Worddokument eingefügt, auch das läuft.
    Trotzdem werde ich mich in die Artikel und das Thema einlesen, hab vielen lieben Dank. Hab noch was vor mir :)
    hier noch, wo ich mich besonders mit der elenden Freigeberei beschäftige: Excel-Interop-Objekte freigeben.
    Problem, bes. für Anfänger ist: man muss wissen, was ein Objekt ist, und was ein Ausdruck. Weil man darf bei Office-InterOp keine zusammengesetzten Ausdrücke coden, denn dabei werden "on the fly" Com-Wrapper erstellt, die dann aber nicht zugreifbar sind.
    Also man muss einen zusammengesetzten Ausdruck in atomare Bestandteile zerlegen können, da man jedes Com-Releasen muss.