Problem mit WEnd in _IELoadWait

  • Hallo zusammen,

    ich bediene per Skript ein Portal im Webbrowser. Nur stoße ich zur Zeit häufig auf folgende Fehlermeldung

    C:\Programme\AutoIt3\Include\TestHelper.au3 (169) : ==> The requested action with this object has failed.:
    Wend
    Wend^ ERROR

    Ich habe einfach kein Plan mehr warum dieser auftritt.

    [autoit]

    Case "DispHTMLWindow2" ; Window, Frame, iFrame
    While Not (String($o_object.document.readyState) = "complete" Or $o_object.document.readyState = 4 Or $f_Abort)
    If (TimerDiff($IELoadWaitTimer) > $i_timeout) Then
    $i_ErrorStatusCode = $_IEStatus_LoadWaitTimeout
    $f_Abort = True
    EndIf
    Sleep(100)
    WEnd
    While Not (String($o_object.top.document.readyState) = "complete" Or $o_object.top.document.readyState = 4 Or $f_Abort)
    If (TimerDiff($IELoadWaitTimer) > $i_timeout) Then
    $i_ErrorStatusCode = $_IEStatus_LoadWaitTimeout
    $f_Abort = True
    EndIf
    Sleep(100)
    Wend

    [/autoit]

    Der Fehler is im Codeausschnitt in Zeile 8.

    When der ObjName "IWebBrowser2" ist, so macht er keine Mucken, aber genau auf der Seite wo er komischerweise "DispHTMLWindow2" ist kommt diese Fehlermeldung.

    Hoffe mir kann jemand helfen.

    Gruß GreS

    Einmal editiert, zuletzt von GreS (23. April 2010 um 07:08)

  • ohne ein vollkommenes script wird dir warscheinlich fast niemand helfen können, nur die, die das mit dem objekt script schon auswendig können
    poste doch bitte einen "funktionierenden schnipsel", damit dir geholfen werden kann ;)
    und warum der sleep???
    Edit1: und schreib lieber:

    [autoit]

    (String($o_object.document.readyState) = "complete" Or (String($o_object.document.readyState) = 4 Or $f_Abort)

    [/autoit]
  • Ich hoffe mit dem Code könnt ihr was anfangen.
    Der genannte Fehler tritt aber nicht immer beim ersten Durchlauf auf, sondern beliebig.

    Skript:

    Spoiler anzeigen
    [autoit]


    #include <TestHelper.au3>
    ; Read the config.ini
    $INI=@ScriptDir&"\AngebotSnagViewConfig.ini"

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

    $host=IniRead ( $INI, "base", "host", "default" )
    $service1=IniRead ( $INI, "base", "service1", "default" )
    $service2=IniRead ( $INI, "base", "service2", "default" )
    $service3=IniRead ( $INI, "base", "service3", "default" )
    $service4=IniRead ( $INI, "base", "service4", "default" )
    $cmd01 = @ScriptDir&"\"& IniRead ( $INI, "base", "cmd01", "default" )

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

    $logWarn=IniRead ( $INI, "check", "logWarning", "default" )
    $logCrit=IniRead ( $INI, "check", "logCritical", "default" )
    $serviceWarn=IniRead ( $INI, "check", "serviceWarn", "default" )
    $serviceCrit=IniRead ( $INI, "check", "serviceCrit", "default" )

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

    $hidden=IniRead ( $INI, "run", "hidden", "true" )

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

    ; Default Options:
    $time = 0
    $user = ""
    $pwd = ""
    $scriptname = @ScriptName
    $scriptdir = @ScriptDir
    $output1=""
    $returncode1=""

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

    ; Ausführung Angebotsschreibung
    While @HOUR < 20
    ; URL und Server wählen
    For $i = 1 to 4 step 1
    if $i = 1 Then
    $url = ""
    $server = "WP_1_1"
    Endif
    if $i = 2 Then
    $url = ""
    $server = "WP_1_2"
    Endif
    if $i = 3 Then
    $url = ""
    $server = "WP_2_1"
    Endif
    if $i = 4 Then
    $url = ""
    $server = "WP_2_2"
    Endif
    ; Angebotsschreibung: Prozess durchführen
    $anwendung = "ANG"
    If $hidden = "true" Then
    ShellExecute("iexplore.exe", $url, "","", @SW_HIDE)
    WinWait("Viessmann Portal")
    $oIE = _IEAttach($url, "url")
    Else
    ShellExecute("iexplore.exe", $url)
    WinWait("Viessmann Portal")
    $oIE = _IEAttach($url, "url")
    EndIf

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

    _IELinkClickByText($oIE, "... treten Sie ein!", "Einstiegsseite laden")
    $oForms = _IEFormGetCollection ($oIE, 0)
    _IEFormElementSetValue(_IEFormElementGetObjByName($oForms, "wps.portlets.userid"), $user)
    _IEFormElementSetValue(_IEFormElementGetObjByName($oForms, "password"), $pwd )
    _IEFormSubmit($oForms, 1)
    $serviceTimeBegin = TimerInit()
    _IELinkClickByText($oIE, "Vertrieb", "Navigation Vertrieb")
    _IELinkClickByText($oIE, "Angebote", "Navigation Angebote")
    _IELinkClickByText($oIE, "Meine Angebotsentwürfe", "Meine Angebotsentwürfe")
    _IELinkClickByText($oIE, "0051234500", "Angebotskopfdaten anzeigen")
    _IELinkClickByText($oIE, "Weiter", "Verkaufshinweis anzeigen")
    _IELinkClickByText($oIE, "Weiter", "Angebotspositionen anzeigen")
    _IELinkClickByText($oIE, "Aktualisieren", "Angebotspositionen aktualisieren")
    _IELinkClickByText($oIE, "Weiter", "Druckeinstellungen anzeigen" )
    _IELinkClickByText($oIE, "Textbaustein auswählen", "Textbaustein auswählen")
    _IELinkClickByText($oIE, "Suchen", "Textbausteine suchen")
    _IELinkClickByText($oIE, "Abgasberechnung", "Auswahl eines Textbausteines")
    $serviceTime = Round(TimerDiff($serviceTimeBegin)/1000, 2)
    _IELinkClickByText($oIE, "Abmelden", "Abmelden")
    _IEQuit($oIE)

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

    ; Returncode und Warn/Crit festlegen
    if $serviceTime >= $serviceCrit Then
    $output1 = StringFormat("%s%s%s", "CRITICAL-",$serviceTime,"s")
    $returncode1 = "2"
    ElseIf $serviceTime >= $serviceWarn Then
    $output1 = StringFormat("%s%s%s", "WARNING-",$serviceTime,"s")
    $returncode1 = "1"
    ElseIf $serviceTime < $serviceWarn Then
    $output1 = StringFormat("%s%s%s", "OK-",$serviceTime,"s")
    $returncode1 = "0"
    EndIf

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

    ; Submit Value to SNAG-View
    ;service1
    If $i = 1 Then
    $performance = "time="&$serviceTime&"s;"&$serviceWarn&";"&$serviceCrit&";0"
    $cmdrun01 = $cmd01 & " " & $host & " " & $service1 & " " & $returncode1 & " " & $output1& " " & $performance
    EndIf
    ;service2
    If $i = 2 Then

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

    $performance = "time="&$serviceTime&"s;"&$serviceWarn&";"&$serviceCrit&";0"
    $cmdrun01 = $cmd01 & " " & $host & " " & $service2 & " " & $returncode1 & " " & $output1& " " & $performance
    EndIf
    ;service3
    If $i = 3 Then

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

    $performance = "time="&$serviceTime&"s;"&$serviceWarn&";"&$serviceCrit&";0"
    $cmdrun01 = $cmd01 & " " & $host & " " & $service3 & " " & $returncode1 & " " & $output1& " " & $performance
    EndIf
    ;service4
    If $i = 4 Then

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

    $performance = "time="&$serviceTime&"s;"&$serviceWarn&";"&$serviceCrit&";0"
    $cmdrun01 = $cmd01 & " " & $host & " " & $service4 & " " & $returncode1 & " " & $output1& " " & $performance
    EndIf
    Run($cmdrun01)
    sleep (5000)
    Next
    Wend
    Exit

    [/autoit]

    TestHelper (include aus Skript)

    Spoiler anzeigen
    [autoit]

    #include-once

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

    ;-- QS Functions --
    ;loggt Antwortzeiten im Projektordner in log\komponente\datum\log.txt
    Func _LogInFile ($projekt, $komponente, $text, $time)
    DirCreate($projekt&"\log\")
    DirCreate($projekt&"\log\"&$komponente&"\" & @YEAR &"_"& @MON &"_"& @MDAY)
    $dir = $projekt&"\log\"&$komponente&"\" & @YEAR &"_"& @MON &"_"& @MDAY & "\"
    $time = Round($time/1000, 2)
    $filename = $dir & "log.txt"
    $file = FileOpen($filename, 1)

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

    ; Status anhand der Antwortzeit setzen
    if $time >= $logCrit Then
    $output = StringFormat("%s%s%s", "CRITICAL;",$time,"s")
    ElseIf $time >= $logWarn Then
    $output = StringFormat("%s%s%s", "WARNING;",$time,"s")
    ElseIf $time < $logWarn Then
    $output = StringFormat("%s%s%s", "OK;",$time,"s")
    EndIf

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

    ;Text der ins das Logfile geschrieben wird
    $filetext = $server&";"&$anwendung&";"&_DateTimeFormat(_NowCalc(), 2)& ";" & _DateTimeFormat(_NowCalc(), 3) & ";" & $text & ";" &$output& @CRLF
    FileWrite( $file, $filetext)
    FileClose($file)
    EndFunc

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

    ;analog zu _LogInFile -> hier sind jedoch die Kriterien für die Zeit anders gesetz
    Func _BAPILogInFile ($projekt, $komponente, $text, $time)
    DirCreate($projekt&"\log\")
    DirCreate($projekt&"\log\"&$komponente&"\" & @YEAR &"_"& @MON &"_"& @MDAY)
    $dir = $projekt&"\log\"&$komponente&"\" & @YEAR &"_"& @MON &"_"& @MDAY & "\"

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

    $time = Round($time/1000, 2)
    $filename = $dir & "log.txt"
    $file = FileOpen($filename, 1)

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

    ; Status anhand der Antwortzeit setzen
    if $time >= 10000 Then
    $output = StringFormat("%s%s%s", "CRITICAL;",$time,"ms")
    ElseIf $time >= 5000 Then
    $output = StringFormat("%s%s%s", "WARNING;",$time,"ms")
    ElseIf $time < 5000 Then
    $output = StringFormat("%s%s%s", "OK;",$time,"ms")
    EndIf

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

    $filetext = $server&";"&$anwendung&";"&_DateTimeFormat(_NowCalc(), 2)& ";" & _DateTimeFormat(_NowCalc(), 3) & ";" & $text & ";" &$output& @CRLF
    FileWrite( $file, $filetext)
    FileClose($file)
    EndFunc

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

    ;Wartet bis Fenster aktiv -> ggf. aktiviert es Fenster
    Func _WinWaitActivate($title,$text,$timeout=0)
    WinWait($title,$text,$timeout)
    If Not WinActive($title,$text) Then WinActivate($title,$text)
    WinWaitActive($title,$text,$timeout)
    EndFunc

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

    ;Return $oIE
    Func _PortalLogin($user = "", $pwd = "", $url = "http://sportal.viessmann.com/wps/myportal", $hidden = "false")
    If $hidden = "true" then
    $oIE=_IECreate($url,0,0)
    else
    $oIE=_IECreate($url)
    endif
    _IELinkClickByText($oIE, "... treten Sie ein!", "Ins Portal eintreten")
    $oForms = _IEFormGetCollection ($oIE, 0)
    if _IEFormElementGetObjByName($oForms, "username") <> 0 Then
    $o_user = _IEFormElementGetObjByName($oForms, "username")
    Else
    $o_user = _IEFormElementGetObjByName($oForms, "wps.portlets.userid")
    EndIf
    $o_pwd = _IEFormElementGetObjByName($oForms, "password")
    _IEFormElementSetValue($o_user, $user)
    _IEFormElementSetValue($o_pwd, $pwd )
    _IEFormSubmit($oForms, 1)
    Return $oIE
    EndFunc

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

    Func _PortalLogout(ByRef $oIE)
    _IELinkClickByText($oIE, "Abmelden", "Abmelden vom Portal")
    _IEQuit($oIE)
    EndFunc

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

    ;-- IE Functions --
    Func _IELoadWait(ByRef $o_object, $i_delay = 0, $i_timeout = -1)
    Local $oTemp, $f_Abort = False, $i_ErrorStatusCode = $_IEStatus_Success
    Sleep($i_delay)
    ;
    Local $IELoadWaitTimer = TimerInit()
    If $i_timeout = -1 Then $i_timeout = $__IELoadWaitTimeout
    Switch ObjName($o_object)
    Case "IWebBrowser2"; InternetExplorer
    While Not (String($o_object.readyState) = "complete" Or $o_object.readyState = 4 Or $f_Abort)
    ; Trap unrecoverable COM errors
    If (TimerDiff($IELoadWaitTimer) > $i_timeout) Then
    $i_ErrorStatusCode = $_IEStatus_LoadWaitTimeout
    $f_Abort = True
    EndIf
    Sleep(100)
    WEnd
    While Not (String($o_object.document.readyState) = "complete" Or $o_object.document.readyState = 4 Or $f_Abort)
    If (TimerDiff($IELoadWaitTimer) > $i_timeout) Then
    $i_ErrorStatusCode = $_IEStatus_LoadWaitTimeout
    $f_Abort = True
    EndIf
    Sleep(100)
    WEnd
    Case "DispHTMLWindow2" ; Window, Frame, iFrame
    While Not (String($o_object.document.readyState) = "complete" Or $o_object.document.readyState = 4 Or $f_Abort)
    If (TimerDiff($IELoadWaitTimer) > $i_timeout) Then
    $i_ErrorStatusCode = $_IEStatus_LoadWaitTimeout
    $f_Abort = True
    EndIf
    Sleep(100)
    WEnd
    While Not (String($o_object.top.document.readyState) = "complete" Or $o_object.top.document.readyState = 4 Or $f_Abort)
    If (TimerDiff($IELoadWaitTimer) > $i_timeout) Then
    $i_ErrorStatusCode = $_IEStatus_LoadWaitTimeout
    $f_Abort = True
    EndIf
    Sleep(100)
    Wend
    Case "DispHTMLDocument" ; Document
    $oTemp = $o_object.parentWindow
    While Not (String($oTemp.document.readyState) = "complete" Or $oTemp.document.readyState = 4 Or $f_Abort)
    If (TimerDiff($IELoadWaitTimer) > $i_timeout) Then
    $i_ErrorStatusCode = $_IEStatus_LoadWaitTimeout
    $f_Abort = True
    EndIf
    Sleep(100)
    WEnd
    While Not (String($oTemp.top.document.readyState) = "complete" Or $oTemp.top.document.readyState = 4 Or $f_Abort)
    If (TimerDiff($IELoadWaitTimer) > $i_timeout) Then
    $i_ErrorStatusCode = $_IEStatus_LoadWaitTimeout
    $f_Abort = True
    EndIf
    Sleep(100)
    WEnd
    Case Else ; this should work with any other DOM object
    $oTemp = $o_object.document.parentWindow
    While Not (String($oTemp.document.readyState) = "complete" Or $oTemp.document.readyState = 4 Or $f_Abort)
    If (TimerDiff($IELoadWaitTimer) > $i_timeout) Then
    $i_ErrorStatusCode = $_IEStatus_LoadWaitTimeout
    $f_Abort = True
    EndIf
    Sleep(100)
    WEnd
    While Not (String($oTemp.top.document.readyState) = "complete" Or $o_object.top.document.readyState = 4 Or $f_Abort)
    If (TimerDiff($IELoadWaitTimer) > $i_timeout) Then
    $i_ErrorStatusCode = $_IEStatus_LoadWaitTimeout
    $f_Abort = True
    EndIf
    Sleep(100)
    WEnd
    EndSwitch

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

    Switch $i_ErrorStatusCode
    Case $_IEStatus_Success
    Return SetError($_IEStatus_Success, 0, 1)
    Case $_IEStatus_LoadWaitTimeout
    Return SetError($_IEStatus_LoadWaitTimeout, 3, 0)
    Case $_IEStatus_AccessIsDenied
    Return SetError($_IEStatus_AccessIsDenied, 0, 0)
    Case $_IEStatus_ClientDisconnected
    Return SetError($_IEStatus_ClientDisconnected, 0, 0)
    Case Else
    Return SetError($_IEStatus_GeneralError, 0, 0)
    EndSwitch
    EndFunc ;==>_IELoadWait

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

    Func _IELinkClickByText(ByRef $o_object, $s_linkText, $s_logText, $i_index = 0, $f_wait = 1 )
    If Not IsObj($o_object) Then
    Return SetError($_IEStatus_InvalidDataType, 1, 0)
    EndIf

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

    Local $found = 0, $linktext, $links = $o_object.document.links
    $i_index = Number($i_index)
    For $link In $links
    $linktext = $link.outerText & "" ; Append empty string to prevent problem with no outerText (image) links
    If StringInStr($linktext, $s_linkText) Then
    If ($found = $i_index) Then
    $link.click
    If $f_wait Then
    $begin = TimerInit()
    If _IELoadWait($o_object) = 1 Then
    _LogInFile($scriptdir, $scriptname, "_IELinkClickByText: " & $s_linktext & ";" & $s_logText, TimerDiff($begin))
    Else
    _LogInFile($scriptdir, $scriptname, "_IELinkClickByText: " & $s_linktext & ";" & $s_logText, TimerDiff($begin))
    _IEQuit($o_object)
    EndIf
    Return SetError(@error, 0, -1)
    EndIf
    Return SetError($_IEStatus_Success, 0, -1)
    EndIf
    $found = $found + 1
    EndIf
    Next
    Return SetError($_IEStatus_NoMatch, 0, 0) ; Could be caused by parameter 2, 3 or both

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

    EndFunc ;==>_IELinkClickByText

    [/autoit]

    Einmal editiert, zuletzt von GreS (21. April 2010 um 16:07)

  • 1. setze bitte beide teile in einen spoiler
    2. bitte lade doch ein beispiel für die ini hoch, ich werde in der zwischenzeit das script schonmal durchgenen ;)

    Edit1:
    soll das sowas wie ein programm sein, dass etwas bestimmtes auf einer webside macht?
    wenn ja, dann solltest du zur sicherheit noch einmal die agbs der seite studieren ;)

  • Hey,
    gegen die AGBs der Seite wird nicht verstoßen.

    Ich bin Mitarbeiter bei Viessmann und messe mit diesem Skript die Antwortzeiten des Portals.
    config.ini:

    Spoiler anzeigen


    [base]
    host=Roboter_Portal
    service1=Angebot_1_1
    service2=Angebot_1_2
    service3=Angebot_2_1
    service4=Angebot_2_2
    cmd01=submit.cmd

    [check]
    in Sekunden
    logWarning=5
    logCritical=10

    serviceWarn=30
    serviceCrit=45

    [run]
    hidden=false

  • ich habe mir das mal ein bisschen genauer angeguckt
    mach doch einfach statt shellexecute _IECreate, da ist ein loadwait beinhaltet, vermutlich fehlt in deinem include das hier:

    [autoit]

    #include "WinAPIError.au3"
    #include "IE" ; bei diesem hier bin ich mir nicht wirklich sicher

    [/autoit]

    aber warum willst du das überhaupt mit includen, wenn es doch eh in der IE.au3 beinhaltet ist
    eventuell reißt du die gesamte funktion auseinfander (wegen anfangsdeklarationen usw)

  • Moin,
    ich habe die Methoden der IE.au3 rausgezogen und in meinen "TestHelper" integriert, um den Fehler besser zu lokalisieren.

    Ich benutze ShellExecute, weil ich mehrere Skripte haben werde, die nebeneinander laufen sollen. Bei IECreate macht er immer nur einen Prozess, ich brauche aber quasi für jedes Skript eine seperate Instanz.

    Ich kann das mit der WinAPIError mal probieren, aber ich weiß nicht ob das hilft, da in meinem Skript ja diese Methoden darin nicht aufgerufen werden.

    Trotzdem schon mal vielen Dank für deine Hilfe.

    Ich bin gerade dran, das Skript neu aufzubauen mit der Original IE.au3 und erweitere diese um meine benötigten Methoden.
    Bspw. reicht mir die IELinkClickbyText nicht aus, da die den LinkText matched. Ich brauche aber eine die den contained. Da die Linknamen bei uns generiert werden und da ständig eine neue ID drin steckt. Unsere LInknamen sind quasi: "ID:form1:weiter"
    Deswegen brauche ich ein contains um nur "Weiter" angeben zu können.

    Wenn der Umbau erfolgreich war, melde ich mich nochmal

    Einmal editiert, zuletzt von GreS (22. April 2010 um 07:53)

  • Habe das Skript jetzt neu aufgebaut, der Fehler kommt zur Zeit nocht nicht. Aber mit IECreate kann ich nicht arbeiten, da die Zwei Skripte sich in die Quere kommen.

    Werde es jetzt mit der ShellExecute probieren.

  • ShellExecute wirft auch Probleme. Es scheint, dass sich die Skripte nicht vertragen, da sie auf dasselbe Portal zugreifen, aber andere Dinge tun.

    Kann ein Skript nicht eindeutig eine Instanz eines Browsers verwenden?

  • ich bin mir nicht sicher, aber villt kann man mit _IECreateEmbedded() bestimmte funktionen darauf beziehen (vorraussetzung ein gui mit guictrlcreateobj())
    sonst villt alles in ein script und geschickt aufbauen oder adlibregister benutzen...
    sonst fällt mir momentan nichts mehr ein, ich überlege noch weiter, sobald ich zeit habe ;)

  • Da mein eigentliches Problem gelöst ist, mache ich für das zweite Problem einen neuen Thread auf.

    Aber danke für die Hilfe.