Page 2 sur 2

Re: [..] Pb de Wend dans include IE.au3 (Ligne 560)

Posté : jeu. 22 mars 2012 13:41
par tioxine
Bonjour,

Alors le contexte
Nous avons un site intranet qui permet aux utilisateurs de passer des demandes de soumission de traitements à un outil, CA7 pour ne pas le nommer
Jusque la, des opérateur lisaient les demandes et intervenaient en conséquence
Hors, après analyse, il s'est avéré que 80% de ces demandes pouvaient être traitées de façon automatisée, d'où le robot

La logique
Toutes les 3 minutes
- Connect (Url) ; Liste des demandes reçues
- Pour chaque demande
- Navigate (Ouverture de la demande)
- Navigate (Prise en compte)
...
...
Fpour
- IEquit (Fin de session)
Et le système se rendort pour 3 minutes

Le code

Code : Tout sélectionner

Func _afIEInternalConnect($pUrl, $pLogon, $pPsw, $pFenetre, $pWait, $pLog)
    Local $fenetre = $pFenetre
    SetError(0)

    ; On ouvre ou on navigue dans une fenêtre Internet
    If ($pFenetre = -1) Then
        $fenetre = _IECreate($pUrl,False,True,$pWait)
    Else
        _IENavigate($fenetre, $pUrl ,$pWait)
    EndIf
    If (@error) Then
        _afLogEcrire($pLog, "_afIEInternalConnect", @error , "Connect / Navigate ")
        $fenetre = -1
    Else
        ; Maximiser la fenêtre
        WinSetState("[CLASS:IEFrame]", "", @SW_MAXIMIZE)
        ; On récupère l'url
        Local $_url = _IEPropertyGet($fenetre, "locationurl")
        If (@error) Then
            _afLogEcrire($pLog, "_afIEInternalConnect", @error, "LocationUrl ")
        ElseIf (StringInStr($_url, "https://xxxxxxxxxxxxx") <> 0) Then ; Habil
            ; Récup du handle sur le user et le password
            Local $user = _IEGetObjByName($fenetre, "USER")
            Local $password = _IEGetObjByName($fenetre, "PASSWORD")
            _IEFormElementSetValue($user, $pLogon)
            _IEFormElementSetValue($password, $pPsw)
            ; On récupère le bon bouton
            ; Comme celui ci n'a ni nom, ni id, on le recherche par son tag
            Local $oInputs = _IETagNameGetCollection($fenetre, "input")
            For $oInput In $oInputs
                If ($oInput.value = "valider / confirm") Then
                    $oInput.click() ; Trouvé => Click
                    ExitLoop
                EndIf
            Next
            If (@error) Then
                _afLogEcrire($pLog, "_afIEInternalConnect", @error , "Passage Habil ")
            EndIf
        EndIf
    EndIf

    ; Tout est ok pour l'instant ?
    If (not @error And $pWait) Then
        ; Load complet ?
        _IELoadWait($fenetre)
        If (@error) Then
            _afLogEcrire($pLog, "_afIEInternalConnect", @error , "Chargement page en erreur ")
        Else ; Log sur la bonne page ?
            Local $objTd = _IEGetObjById($fenetre, "tableProps")
            If (not @error) Then
                _afLogEcrire($pLog, "_afIEInternalConnect", $GCERR401 , "Chargement page en erreur ")
                SetError($GCERR401)
            Else
                Sleep(2000) ; Pour être sur que les onload soient ok
            EndIf
        EndIf
    ElseIf (@error) Then
        If ($fenetre <> -1) Then
            _IEQuit($fenetre)
        EndIf
    EndIf



    Return $fenetre
EndFunc 
 
Oila

Re: [..] Pb de Wend dans include IE.au3 (Ligne 560)

Posté : jeu. 22 mars 2012 14:24
par jchd
Plus le peine de se creuser le cerveau, voir mon post précédent.

Re: [..] Pb de Wend dans include IE.au3 (Ligne 560)

Posté : jeu. 22 mars 2012 15:21
par mikell
Heu certes mais c'est quoi au juste le " ticket #2089 " ?

Re: [..] Pb de Wend dans include IE.au3 (Ligne 560)

Posté : jeu. 22 mars 2012 15:48
par jchd
C'est le n° du ticket correspondant à ce bug, sur le site US.

Re: [..] Pb de Wend dans include IE.au3 (Ligne 560)

Posté : jeu. 22 mars 2012 17:33
par mikell
OK !!
Donc en virant toutes les fonctions IE qui utilisent _IELoadWait, ça devrait le faire...
J'avais pas détecté parce que je tourne encore avec la 3.3.6.1 et que j'utilise le plus possible l'objet COM

Code : Tout sélectionner

$oIE = ObjCreate("InternetExplorer.Application")
$oIE.visible = 0
$oIE.navigate("http://www.autoitscript.fr/forum/index.php")
while $oIE.Busy
Sleep(100)
wend
....etc

Re: [..] Pb de Wend dans include IE.au3 (Ligne 560)

Posté : jeu. 22 mars 2012 18:41
par tioxine
Bonjour,

En lisant le thread
[R] Détecter présence objets IE ss attendre chargement page
je crois avoir compris le pb
Le gars, dans ce thread, fait référence au temps de chargement de la page
Si on regarde le timeout de IE, il est de 5 minutes
Supposons maintenant que IE utilise un objet au timeout plus court (wininet.dll ?)
Quand celui ci va arriver en fin, il va disparaitre et provoquer une erreur
J'ai testé cette hypothèse et c'est bien ce qui se passe

Code : Tout sélectionner

#include-once
#include <IE.au3>
Local $fen = _IECreate("http://google.fr")
_IELoadWait($fen)
 
Puis on modifie IE.au3 afin qu'il nous laisse la main qq secondes

Code : Tout sélectionner

ConsoleWrite("============================================================================")
sleep(5000)
 
on ajoute ces lignes derrière la ligne 548

Puis on lance le test
Quand la ligne de === apparait, on ferme google et le résulat, aprés 5 secondes est
============================================================================
C:\PROGRAM FILES (X86)\AUTOIT3\Include\IE.au3 (561) : ==> The requested action with this object has failed.:
WEnd
WEnd^ ERROR

Donc la même que celle décrite avant

Donc il faut vérifier, dans IE.au3 que l'objet est toujours la avant d'agir et le pb devrait être réglé

A+

Re: [..] Pb de Wend dans include IE.au3 (Ligne 560)

Posté : jeu. 22 mars 2012 19:10
par tioxine
Pour la correction, voir les derniers messages

Merci à tous pour votre aide

A+

Re: [R] Pb de Wend dans include IE.au3 (Ligne 560)

Posté : jeu. 22 mars 2012 21:01
par tioxine
Sans objet (Voir derniers messages)

A+

Re: [R] Pb de Wend dans include IE.au3 (Ligne 560)

Posté : sam. 24 mars 2012 17:14
par tioxine
Idem que ci dessus

Re: [..] Pb de Wend dans include IE.au3 (Ligne 560)

Posté : lun. 26 mars 2012 14:00
par AkoU
j'ai pas encore essayé mais si ça marche j'ai envie de dire : GENIE !!! car je bug là-dessus depuis plusieurs semaine ^^

Re: [..] Pb de Wend dans include IE.au3 (Ligne 560)

Posté : mar. 27 mars 2012 19:04
par tioxine
Voir derniers messages

A+

Re: [..] Pb de Wend dans include IE.au3 (Ligne 560)

Posté : mar. 27 mars 2012 23:22
par tioxine
Alleluia, enfin, j'ai trouvé :o
C'est l'utilisation de la fonction __IEIsObjType qui nous pose tous ces pb
Voir ci dessous
A+

Re: [..] Pb de Wend dans include IE.au3 (Ligne 560)

Posté : mer. 28 mars 2012 00:31
par tioxine
Bon, ok j'ai toutes les explications

Lorsque l'on s'enregistre en ligne 535, c'est ok

Code : Tout sélectionner

Local $status = __IEInternalErrorHandlerRegister()


MAIS lorsque l'on commence la boucle

Code : Tout sélectionner

Case __IEIsObjType($o_object, "browser"); InternetExplorer
ligne 551, on passe par la fonction
__IEIsObjType qui elle même commence par __IEInternalErrorHandlerRegister() ET se finit par __IEInternalErrorHandlerDeRegister()
Hors cette fonction [__IEInternalErrorHandlerDeRegister()] ne recharge le handler précédent que si celui ci a été enregistré dans $sIEUserErrorHandler ce que ne fait pas __IEInternalErrorHandlerRegister()
Du coup, après l'exécution de __IEIsObjType, on n'as plus de fct pour trapper les erreurs COM

Alors , la correction
A partir d'un IE.au3 original
Ligne 536

Code : Tout sélectionner

$sIEUserErrorHandler = ObjEvent("AutoIt.Error")
On stocke le handler pour éviter de le perdre aprés l'exécution de IEIsObjType
Ensuite, il va falloir récupérer correctement l'erreur, ce que ne permet pas les boucles telles que faite [Ligne 552 au EndSelect]

Voici la correction pour le 1er cas , il faudra faire pareil pour les autres

Code : Tout sélectionner

Local $value
Case __IEIsObjType($o_object, "browser"); InternetExplorer
            $value = $o_object.readyState
            $i_ErrorStatusCode = @error
            While Not ($i_ErrorStatusCode Or String($value) = "complete" Or $value = 4 Or $f_Abort)
                If (TimerDiff($IELoadWaitTimer) > $i_timeout) Then
                    $i_ErrorStatusCode = $_IEStatus_LoadWaitTimeout
                    $f_Abort = True
                EndIf
                ; Trap unrecoverable COM errors
                If @error = $_IEStatus_ComError And __IEComErrorUnrecoverable() Then
                    $i_ErrorStatusCode = __IEComErrorUnrecoverable()
                    $f_Abort = True
                EndIf
                Sleep(100)
                $value = $o_object.readyState
                $i_ErrorStatusCode = @error
            WEnd
            $value = 0
            While Not ($i_ErrorStatusCode Or String($value) = "complete" Or $value = 4 Or $f_Abort)
                If (TimerDiff($IELoadWaitTimer) > $i_timeout) Then
                    $i_ErrorStatusCode = $_IEStatus_LoadWaitTimeout
                    $f_Abort = True
                EndIf
                ; Trap unrecoverable COM errors
                If @error = $_IEStatus_ComError And __IEComErrorUnrecoverable() Then
                    $i_ErrorStatusCode = __IEComErrorUnrecoverable()
                    $f_Abort = True
                EndIf
                Sleep(100)
                $value = $o_object.document.readyState
                $i_ErrorStatusCode = @error
            WEnd
 
Voila
A partir de la, tout fonctionne correctement et l'erreur COM est bien remontée et trappée

A+

Re: [..] Pb de Wend dans include IE.au3 (Ligne 560)

Posté : mer. 28 mars 2012 02:17
par jchd
Très bien. Si tu es certain de ton coup, mets-toi en directement contact avec l'auteur, DaleHohm sur le forum US.

Re: [..] Pb de Wend dans include IE.au3 (Ligne 560)

Posté : mer. 28 mars 2012 08:50
par tioxine
Sur de mon coup, oui
En fait, c'est la gestion des erreurs en totalité qui est foireuse
Il faudrait stocker le niveau dans une variable et executer objetevent si et seulement si niv = 1

Exemple
Appel _IExxx01 => InternalRegister (niveau 1) [si niv=1 alors objetevent sinon rien , donc objetevent (niv 1)]
Apple _IExxx02 => InternalRegister (n2) [rien car le niveau n'est pas 1]
InternelDeregister (n2) [niv - 1 ; Si niv = 1 alors objetevent sinon rien, donc,ici rien]
......
......
InternelDeregister (n1) [Niv = 1, donc on remet objetEvent]

Voila, la gestion des erreurs est ok (on ne perd jamais la fct qui trappe les erreurs COM, et ,au retour, on remet correctement AutoIt Error)

Sauf que, ensuite, il faut s'attaquer à la gestion du @error dans la fonction
En effet, toutes les fonctions de AutoIt réinit le @error , donc, si on ne s’intéresse pas à la valeur immédiatement, c'est mort
Exemple If (String($obj.document.readyState) = "xxxxx" Or String($toto) = "rrr" Or @error <> 0) ... ne fonctionnera pas car String met @error à zéro d'ou l'obligation de couper les ordres
A) $value = $obj.document.readyState
B) If @error .... ; L'erreur est testée immédiatement
If (String($value) ....)

Voila, ceci devrait permettre un fct tout à fait correcte de cet excellent plugin

Quand à contacter delhorme, oui, bien sur, mais mon anglais est nul.
Il va avoir du mal à comprendre le pauvre

A+

Re: [..] Pb de Wend dans include IE.au3 (Ligne 560)

Posté : ven. 30 mars 2012 11:32
par tioxine
[R] Pb de Wend dans include IE.au3 (Ligne 560)

Bon, je confirme, ça marche
Correction le 28/03, nous sommes le 30 et aucun incident sur ce plugin
(Je rappelle pour mémoire : 24/24, 7/7 toutes les 3 minutes)
Avant : 1 à 4 pépins du style Wend ..., maintenant 0

Pour ceux que ça intéresse, le fichier IE.au3 corrigé est en PJ
Ne pas modifier celui qui est dans le rep include, mais le copier dans une dir utilisateur et remplacer #include <IE.au3> par #include "chemin/IE.au3"
IE.au3
(190.78 Kio) Téléchargé 9454 fois
A+