Crash mit Word.au3

  • Hallo Zusammen

    Eines meiner Programme macht mir unerwartet Probleme, die ich mir nicht erklären kann. Ich hoffe, ihr habt dafür vielleicht eine Lösung.

    Zu den Rahmenbedingungen:
    Mein Programm wird von verschiedenen Benutzern an verschiedenen Computern benutzt und aktualisiert sich bei Bedarf über eine gemeinsame Netzwerkquelle.
    Ein Teil seiner Funktion ist es, dass mittels HotkeySet ein vorhandenes Word-Dokument geöffnet, eine GUI zur Abfrage zusätzlicher Informationen eingeblendet wird und nach dem schließen der GUI eine entsprechende Anpassung des Word-Dokument mit anschließenden Druck erfolgt - eigentlich sehr simpel.

    Nun hat es sich bei einer neuen Benutzerin ergeben, dass das Programm beim Start der entsprechenden Funktion abstürzt - jedoch nur bei dieser Benutzerin.
    Als Erklärung gibt es dazu die folgende Meldung:

    Titel "Autoit Error"
    Line 5486 (File "\\[...].exe"):
    Error: The requested action with this object has failed.


    Der Quellcode samt Includes sieht, zur Übersichtlichkeit gekürzt, wie folgt aus.

    [autoit]

    #include <Array.au3>
    #include <Date.au3>
    #include <EditConstants.au3>
    #include <GUIConstantsEx.au3>
    #include <GuiListBox.au3>
    #include <ListBoxConstants.au3>
    #include <WindowsConstants.au3>
    #include <Word.au3>
    Opt("WinTitleMatchMode", 1)
    Opt("TrayAutoPause", 0)

    [/autoit][autoit][/autoit][autoit]

    Func _bestp()
    Local $sdbvar, $hand, $name, $datearray[1], $var2 = 1, $araten, $oDoc
    If WinExists("SDB") Then
    $sdbksvar = 1
    $hand = _WordCreate(@MyDocumentsDir & "\sdb_zahlung.doc")
    $name = "sdb_zahlung"
    Else
    $hand = _WordCreate(@MyDocumentsDir & "\Zahlung.doc")
    $name = "zahlung"
    EndIf

    [/autoit][autoit][/autoit][autoit]

    If Not @error Then
    WinWait($name)
    $oDoc = _WordDocGetCollection($hand, 0)
    ;[....] Script gekürzt

    [/autoit][autoit][/autoit][autoit]

    Else
    $pid = WinGetProcess($name)
    $i = 1
    $list = ProcessList("WINWORD.exe")
    If $list[0][0] > 1 Then
    Do
    If $list[$i][1] <> $pid Then ProcessClose($list[$i][1])
    $i = $i + 1
    Until $i >= $list[0][0]
    WinActivate($name)
    Send("{F4}")
    Else
    MsgBox(48, "", "Schreiben konnte nicht erkannt werden. Bitte Schreiben schließen und erneut öffnen.")

    [/autoit][autoit][/autoit][autoit]

    EndIf
    EndIf
    EndFunc

    [/autoit]


    Mit simplen MsgBox bin ich zumindest so weit gekommen, dass der Absturz mit dem Befehl $hand = _WordCreate(@MyDocumentsDir & "\ geschieht.

    Mir erschließt sich allerdings nicht, warum. Soweit ersichtlich ist die Word-Version des Computers identisch zu den anderen. :( Es handelt sich hier um das etwas betagte Word 2003.
    Hat jemand von Euch eine Idee, woran er sich stören könnte? ?(

  • Zwei Dinge fallen mir ein:

    • Ein COM error handler sollte mehr Informationen übr den aufgetretenen Fehler bringen. Ein Beispiel findet sich in der Hilfe unter ObjEvent
    • Ist auf diesem PC die volle Office Installation? Also keine Trial Version? Dann fehlt nämlich COM.
  • Zwei Dinge fallen mir ein:

    • Ein COM error handler sollte mehr Informationen übr den aufgetretenen Fehler bringen. Ein Beispiel findet sich in der Hilfe unter ObjEvent
    • Ist auf diesem PC die volle Office Installation? Also keine Trial Version? Dann fehlt nämlich COM.

    Auf dem Computer ist wie auf allen anderen eine Vollversion von Office 2003 installiert - unter Windows XP.
    Kannst du mir das mit dem Com Error Handler etwas näher erläutern?

  • Beispiel:

    [autoit]

    Global $oErrorHandler = ObjEvent("AutoIt.Error", "_ErrFunc")

    [/autoit][autoit][/autoit][autoit]

    ; Dein Script gehört hier herein

    [/autoit][autoit][/autoit][autoit]

    ; User's COM error function. Will be called if COM error occurs
    Func _ErrFunc($oError)
    ConsoleWrite(@ScriptName & " (" & $oError.scriptline & ") : ==> COM Error intercepted !" & @CRLF & _
    @TAB & "err.number is: " & @TAB & @TAB & "0x" & Hex($oError.number) & @CRLF & _
    @TAB & "err.windescription:" & @TAB & $oError.windescription & @CRLF & _
    @TAB & "err.description is: " & @TAB & $oError.description & @CRLF & _
    @TAB & "err.source is: " & @TAB & @TAB & $oError.source & @CRLF & _
    @TAB & "err.helpfile is: " & @TAB & $oError.helpfile & @CRLF & _
    @TAB & "err.helpcontext is: " & @TAB & $oError.helpcontext & @CRLF & _
    @TAB & "err.lastdllerror is: " & @TAB & $oError.lastdllerror & @CRLF & _
    @TAB & "err.scriptline is: " & @TAB & $oError.scriptline & @CRLF & _
    @TAB & "err.retcode is: " & @TAB & "0x" & Hex($oError.retcode) & @CRLF & @CRLF)
    EndFunc ;==>_ErrFunc

    [/autoit]
  • Hm... hab es auf meinem "funktionierenden Computer" getestet, da wollte er über _WordErrorHandlerDeRegister() erst einmal einen benutzerdefinierten ErrorHandler haben, da er auf den Internen nicht zugreifen konnte.
    Entsprechend der Dokumentation hab ich es dann so angepasst.

    [autoit]

    Func _bestp()
    Local $sdbvar, $hand, $name, $datearray[1], $var2 = 1, $araten, $oDoc
    _WordErrorHandlerRegister("MyErrFunc")

    If WinExists("SDB") Then
    $sdbksvar = 1
    $hand = _WordCreate(@MyDocumentsDir & "\sdb_zahlung.doc")
    $name = "sdb_zahlung"
    Else
    $hand = _WordCreate(@MyDocumentsDir & "\Zahlung.doc")
    $name = "zahlung"
    EndIf
    _WordErrorHandlerDeRegister()
    ; Registriert den Standard-Errorhandler aus Word.au3
    _WordErrorHandlerRegister()

    [/autoit][autoit][/autoit][autoit][/autoit][autoit]

    If Not @error Then
    WinWait($name)
    $oDoc = _WordDocGetCollection($hand, 0)
    ;[....] Script gekürzt

    [/autoit]


    Statt in die Console hab ich das ganze in eine TXT-Datei umgeleitet.
    Nach meiner Funktion hab ich die Func _ErrFunc($oError) eingebaut und mal bei mir testweise gestartet.
    Nun klappt meine Funktion, erstmal der Aufruf des Word-Dokuments, auch bei mir nicht mehr.
    Die TXT-Datei wird stattdessen in einer Schleife mit dem folgenden befüllt:

    160114.au3 (0) : ==> COM Error intercepted !
    err.number is: 0x00000000
    err.windescription: 0
    err.description is: 0
    err.source is: 0
    err.helpfile is: 0
    err.helpcontext is: 0
    err.lastdllerror is: 0
    err.scriptline is: 0
    err.retcode is: 0x00000000
    ?(?(

  • Dann wollen wir doch mal einen einfachen Reproducer produzieren:

    [autoit]

    #include <Word.au3>
    Global $oError = ObjEvent("AutoIt.Error", "_ErrFunc")
    Global $hand = _WordCreate(@MyDocumentsDir & "\sdb_zahlung.doc")
    Func _ErrFunc($oError)
    ConsoleWrite(@ScriptName & " (" & $oError.scriptline & ") : ==> COM Error intercepted !" & @CRLF & _
    @TAB & "err.number is: " & @TAB & @TAB & "0x" & Hex($oError.number) & @CRLF & _
    @TAB & "err.windescription:" & @TAB & $oError.windescription & @CRLF & _
    @TAB & "err.description is: " & @TAB & $oError.description & @CRLF & _
    @TAB & "err.source is: " & @TAB & @TAB & $oError.source & @CRLF & _
    @TAB & "err.helpfile is: " & @TAB & $oError.helpfile & @CRLF & _
    @TAB & "err.helpcontext is: " & @TAB & $oError.helpcontext & @CRLF & _
    @TAB & "err.lastdllerror is: " & @TAB & $oError.lastdllerror & @CRLF & _
    @TAB & "err.scriptline is: " & @TAB & $oError.scriptline & @CRLF & _
    @TAB & "err.retcode is: " & @TAB & "0x" & Hex($oError.retcode) & @CRLF & @CRLF)
    EndFunc ;==>_ErrFunc

    [/autoit]

    Kannst Du den bitte mal laufen lassen?

  • Noch ne Frage:
    Mit welcher AutoIt Version arbeitest Du?

  • Noch ne Frage:
    Mit welcher AutoIt Version arbeitest Du?

    Die Autoit3.exe ist Version 3.3.4.0, der von mir verwendete SciTE.exe hat die Version 1.7.9.0.
    Hab dein Schnipsel gerade mal in eine neue Au3 gepackt und gestartet, gleiches Ergebnis. Neben dem Hinweis
    Word.au3 Warning from function _WordCreate, Cannot register internal error handler, cannot trap COM errors (Use _WordErrorHandlerRegister() to register a user error handler)
    wird die Konsole gefühlt endlos hiermit gefüllt:

  • 3.3.4.0 ist natürlich schon 4 Jahre alt. Da hat sich die Art, wie der Error handler funtkioniert, geändert:

    [autoit]

    #include <Word.au3>
    Global $oError = ObjEvent("AutoIt.Error", "_ErrFunc")
    Global $hand = _WordCreate(@MyDocumentsDir & "\sdb_zahlung.doc")
    Func _ErrFunc()
    ConsoleWrite(@ScriptName & " (" & $oError.scriptline & ") : ==> COM Error intercepted !" & @CRLF & _
    @TAB & "err.number is: " & @TAB & @TAB & "0x" & Hex($oError.number) & @CRLF & _
    @TAB & "err.windescription:" & @TAB & $oError.windescription & @CRLF & _
    @TAB & "err.description is: " & @TAB & $oError.description & @CRLF & _
    @TAB & "err.source is: " & @TAB & @TAB & $oError.source & @CRLF & _
    @TAB & "err.helpfile is: " & @TAB & $oError.helpfile & @CRLF & _
    @TAB & "err.helpcontext is: " & @TAB & $oError.helpcontext & @CRLF & _
    @TAB & "err.lastdllerror is: " & @TAB & $oError.lastdllerror & @CRLF & _
    @TAB & "err.scriptline is: " & @TAB & $oError.scriptline & @CRLF & _
    @TAB & "err.retcode is: " & @TAB & "0x" & Hex($oError.retcode) & @CRLF & @CRLF)
    EndFunc ;==>_ErrFunc

    [/autoit]


    Aber vielleicht probierst Du es ja auch mit einem Upgrade auf 3.3.8.1 oder 3.3.10.2?

  • 3.3.4.0 ist natürlich schon 4 Jahre alt. Da hat sich die Art, wie der Error handler funtkioniert, geändert:
    [...]
    Aber vielleicht probierst Du es ja auch mit einem Upgrade auf 3.3.8.1 oder 3.3.10.2?

    3.3.10.2 müsste ich erst mit administrativen Berechtigungen installieren - was ich auf meinem Arbeitscomputer nicht wirklich mag; mein "altes AutoIt" kann ich problemlos ohne Installation benutzen.
    Hab dein Error-Handler gerade mal mit meiner alten Version an meinem eigentlich funktionierenden Computer probiert.
    Word-Dokument wird geöffnet, aber in der Console trotzdem folgendes geschrieben:

    --> Word.au3 Warning from function _WordCreate, Cannot register internal error handler, cannot trap COM errors (Use _WordErrorHandlerRegister() to register a user error handler)
    Error_Handler.au3 (155) : ==> COM Error intercepted !
    err.number is: 0x800401E3
    err.windescription: Vorgang nicht verfügbar.

    err.description is:
    err.source is:
    err.helpfile is:
    err.helpcontext is:
    err.lastdllerror is: 14007
    err.scriptline is: 155
    err.retcode is: 0x00000000

    --> Word.au3 Warning from function internal function __WordIsObjType, Cannot register internal error handler, cannot trap COM errors (Use _WordErrorHandlerRegister() to register a user error handler)
    +>09:41:39 AutoIT3.exe ended.rc:0
    >Exit code: 0 Time: 5.086

  • Kannst Du bitte die Zeile 155 aus dem Word UDF hier posten?
    In der Version 3.3.8.1 steht da:

    [autoit]

    Local $o_object = ObjGet("", "Word.Application")

    [/autoit]
  • Kannst Du bitte die Zeile 155 aus dem Word UDF hier posten?
    In der Version 3.3.8.1 steht da:

    [autoit]

    Local $o_object = ObjGet("", "Word.Application")

    [/autoit]

    Ist hier identisch
    Local $o_object = ObjGet("", "Word.Application")

    Word.au3 ist
    ; Version: V1.0-1
    ; Last Update: 4/14/07

  • Diese Zeile sollte eigentlich

    bringen, falls Word nicht läuft.
    "Vorgang nicht verfügbar" deutet auf ein Installationsproblem von Office hin.

  • Vielleicht beschreibt dieser Artikel das Problem.
    Ich ahtte mal ein ähnliches Problem mit einem schlecht programmierten Add-On. Kannst Du mal alle Add-Ons in Word ausschalten und nochmals testen?

  • Vielleicht beschreibt dieser Artikel das Problem.
    Ich ahtte mal ein ähnliches Problem mit einem schlecht programmierten Add-On. Kannst Du mal alle Add-Ons in Word ausschalten und nochmals testen?

    Eigentlich sind wir ja jetzt etwas vom Kurs abgekommen, bei meinem Computer hatte das ja immer funktioniert.^^
    Hab jetzt mal beim betroffenen Computer beides getestet.

    Hab dein ObjEvent die Ausgabe in eine TXT machen lassen, positiv ist schon mal, das Word-Dokument geht auf.
    Dazu die folgende Fehlerausgabe:


    Hab danach mal meinen unveränderten Quellcode getestet, da gab es wieder den Absturz ohne öffnen des Word-Dokument. ?(

  • Da gehen mir nun langsam echt die Ideen aus!!

  • Hab es jetzt mal beim Problem-Computer mit deinem ErrorHandler in meinem Code getestet.
    Der einzige Fehler ist...

    Code
    Hotkey.exe (-1) : ==> COM Error intercepted !
    	err.number is: 		0x80020009
    	err.windescription:	
    	err.description is: 	Unzureichender Arbeitsspeicher. Speichern Sie jetzt Ihr Dokument.
    	err.source is: 		Microsoft Word
    	err.helpfile is: 	C:\Programme\Microsoft Office\OFFICE11\1031\wdmain11.chm
    	err.helpcontext is: 	24577
    	err.lastdllerror is: 	0
    	err.scriptline is: 	-1
    	err.retcode is: 	0x800A13E9

    Was mir auffällt, am Ende der problematischen Funktion habe ich den folgenden Code:

    [autoit]

    Else
    $pid = WinGetProcess($name)
    $i = 1
    $list = ProcessList("WINWORD.exe")
    If $list[0][0] > 1 Then
    Do
    If $list[$i][1] <> $pid Then ProcessClose($list[$i][1])
    $i = $i + 1
    Until $i >= $list[0][0]
    WinActivate($name)
    Send("{F4}")
    Else
    MsgBox(48, "", "Schreiben konnte nicht erkannt werden. Bitte Schreiben schließen und erneut öffnen.")

    [/autoit][autoit][/autoit][autoit]

    EndIf
    EndIf

    [/autoit]

    Dieses Else, Zeile 1, bezieht sich auf die Zeile "If Not @error Then", welche nach dem öffnen des Word-Dokument kommt.
    Damit habe ich, wenn die Erkennung des Word-Prozess/Fenster nicht funktioniert hat, zusätzliche Prozesse mit dem Namen WINWORD.exe aufgelistet und beendet. Nur wenn auch das nicht funktioniert hat, kam die MsgBox, Zeile 13, mit der Bitte, das Schreiben zu schließen.
    Hängt das irgendwie zusammen?

  • Du erstellst auf der einen Seite ein Word Dokument über COM (_WordCreate), beendest Word dann aber über die Automatisierung des GUI.
    Warum verwendest Du nicht einfach

    [autoit]

    _WordQuit($hand)

    [/autoit]
  • Du erstellst auf der einen Seite ein Word Dokument über COM (_WordCreate), beendest Word dann aber über die Automatisierung des GUI.
    Warum verwendest Du nicht einfach

    [autoit]

    _WordQuit($hand)

    [/autoit]

    Ich beende ja nicht mein eigenen Handle. Nur wenn er das erstellte Word-Dokument nicht finden kann, ist passiert wenn weitere Prozesse mit dem Namen Winword.exe existierten, sollte er diese weiteren Prozesse schließen.

    [autoit]

    #include <Array.au3>
    #include <Date.au3>
    #include <EditConstants.au3>
    #include <GUIConstantsEx.au3>
    #include <GuiListBox.au3>
    #include <ListBoxConstants.au3>
    #include <WindowsConstants.au3>
    #include <Word.au3>
    Opt("WinTitleMatchMode", 1)
    Opt("TrayAutoPause", 0)

    [/autoit][autoit][/autoit][autoit]

    Func _bestp()
    Local $sdbvar, $hand, $name, $datearray[1], $var2 = 1, $araten, $oDoc
    If WinExists("SDB") Then
    $sdbksvar = 1
    $hand = _WordCreate(@MyDocumentsDir & "\sdb_zahlung.doc")
    $name = "sdb_zahlung"
    Else
    $hand = _WordCreate(@MyDocumentsDir & "\Zahlung.doc")
    $name = "zahlung"
    EndIf

    [/autoit][autoit][/autoit][autoit]

    If Not @error Then
    WinWait($name)
    $oDoc = _WordDocGetCollection($hand, 0)
    ;[....] Script gekürzt
    If WinExists("Microsoft Word") Then WinClose("Microsoft Word")

    [/autoit][autoit][/autoit][autoit]

    Else
    $pid = WinGetProcess($name)
    $i = 1
    $list = ProcessList("WINWORD.exe")
    If $list[0][0] > 1 Then
    Do
    If $list[$i][1] <> $pid Then ProcessClose($list[$i][1])
    $i = $i + 1
    Until $i >= $list[0][0]
    WinActivate($name)
    Send("{F4}")
    Else
    MsgBox(48, "", "Schreiben konnte nicht erkannt werden. Bitte Schreiben schließen und erneut öffnen.")

    [/autoit][autoit][/autoit][autoit]

    EndIf
    EndIf
    EndFunc

    [/autoit]

    Mit deinem

    [autoit]

    _WordQuit($hand)

    [/autoit]

    würde ich ja nur mein Handle beenden.

  • Check ich nicht ganz. Warum willst Du andere Word Prozesse schliessen?
    Der User hat 2 Word Dokumente offen, drückt den Hotkey (wie von Dir in Post 1 beschrieben), Du öffnest das Dokument. Wenn dann ein in der Verarbeitung ein Fehler auftritt, soll doch nur das von Dir geöffnete Dokument geschlossen werden.
    Oder verstehe ich da was miss?