Page 1 sur 1
[R] Erreur suite à saturation mémoire ?
Posté : mer. 15 juin 2016 14:43
par jpascal
Bonjour,
J'ai créé un script qui récupère une liste d'une page HTML à l'aide du code HTML et de RegEx.
Ensuite, je teste si la case de chaque objet de la liste est coché avec ce code et j'ajoute son nom dans un fichier si c'est le cas :
Code : Tout sélectionner
For $i = 0 To UBound($aArray) - 1 Step 2
$res = _IEFormElementCheckBoxSelect($oForm, 0, $sPrefixe & $aArray[$i] & $sSuffixe, -1, "byIndex")
If @error Then Exit MsgBox($MB_SYSTEMMODAL + $MB_ICONERROR, '', 'Erreur ' & @error & ' (' & $aArray[$i] & ')')
If $res = 1 Then FileWrite($hFile, $aArray[$i + 1] & @CRLF)
Next
Le programme plante aléatoirement.
Là je viens de faire des essais, ça plante à l'objet 450.
La récupération de la liste est immédiate mais mon tableau contient plus de 2200 entrées.
Je pense que c'est un problème mémoire. Comment puis-je le vérifier ? Le régler ?
Re: [..] Erreur suite à saturation mémoire ?
Posté : mer. 15 juin 2016 15:19
par TomAijerrie
Pour vérifier, tu peux lancer le gestionnaire des taches (Ctrl + Maj + Echap) et tu regarde la courbe d'utilisation de la mémoire RAM.
Si ça viens un peut trop près du plafond, c'est que le problème est effectivement un problème memoire.
Re: [..] Erreur suite à saturation mémoire ?
Posté : mer. 15 juin 2016 16:18
par orax
Quelle est exactement l'erreur lors du plantage ?
Re: [..] Erreur suite à saturation mémoire ?
Posté : jeu. 16 juin 2016 16:17
par jpascal
L'utilisation mémoire ne varie pas.
L'erreur est :
Code : Tout sélectionner
IE.au3 T3.0-2 Warning from function _IEFormElementCheckBoxSelect, $_IESTATUS_NoMatch
Donc grosso modo, il récupère correctement l'état des 450 premières cases à cocher.
Les 120 tests suivants, j'obtiens cette erreur.
Ensuite AutoIt plante avec une belle fenêtre : "AutoIt v3 Script a cessé de fonctionner."
Et le déboqueur indique : "Une exception win32 non gérée s'est produite dans AutoIt.exe"
Re: [..] Erreur suite à saturation mémoire ?
Posté : ven. 17 juin 2016 15:37
par jpascal
A noter que l'erreur n'est pas systématique. Je peux l'avoir deux fois et cela fonctionnera au troisième essai.
De plus, si je remplace For $i = 0 par For $i = 2 ou For $i = 4, la case à cocher posant problème sera décalée d'autant.
On peut donc exclure un problème dans le code source de la page.
Le problème doit se situer au niveau de l'UDF IE.au3
Rajouter un Sleep(100) dans la boucle ne change rien.
Re: [..] Erreur suite à saturation mémoire ?
Posté : jeu. 23 juin 2016 12:56
par jpascal
Si je récupère à nouveau le contenu de mon cadre puis de mon formulaire, le traitement peut poursuivre.
Mais à la seconde erreur, c'est inefficace.
La seule solution trouvée est d'enregistrer la checkbox où le traitement est en erreur et de relancer le programme.
La page web n'étant pas actualisée, le programme se situe donc bien au niveau d'AutoIt (fuite mémoire ?)
Re: [..] Erreur suite à saturation mémoire ?
Posté : jeu. 23 juin 2016 14:01
par orax
J'ai essayé de reproduire le problème, pour voir quelle en serait l'origine, mais sans succès. Donc c'est assez difficile de t'aider puisque je n'ai pas de plantage.
Dans le but de pouvoir reproduire les plantages, serait-il possible d'avoir l'adresse du site ou le code HTML qui pose des problèmes ?
Re: [..] Erreur suite à saturation mémoire ?
Posté : jeu. 23 juin 2016 15:11
par jpascal
Le site étant interne, il m'est impossible de donner un accès.
J'ai donc enregistré le code source et nettoyé certaines références.
Voici le lien de téléchargement :
http://dl.free.fr/nXecO8tbi
A noter que la page originale est plus lourde, je n'ai conservé que la partie tableau contenant les fameuses checkbox.
Le tableau contenant toutes les tâches est généré comme cela :
Code : Tout sélectionner
$ePrefixe = "m_c_gridTasks_v_ctl"
$eSuffixe = "_s"
$sPattern = '<label for="' & $ePrefixe & '(\d+)' & $eSuffixe & '">.*?onmouseout="UnTip\(\)">(.*?)</span></td><td class="wrap-normal">'
$aArray = StringRegExp($sHTML, $sPattern, 3)
Re: [..] Erreur suite à saturation mémoire ?
Posté : jeu. 23 juin 2016 18:02
par orax
Je n'ai toujours pas d'erreur.
Code : Tout sélectionner
#include <IE.au3>
$sURL = 'http://au3.96.lt/temp/prob_autoit.html'
$oIE = _IECreate($sURL)
;~ $oIE = _IEAttach('prob_autoit.html', 'url')
Sleep(10000) ; le temps de cocher des cases
For $j = 1 To 50
$sHTML = _IEBodyReadHTML($oIE)
$sPrefixe = "m_c_gridTasks_v_ctl"
$sSuffixe = "_s"
$sPattern = '<label for="' & $sPrefixe & '(\d+)' & $sSuffixe & '">.*?onmouseout="UnTip\(\)">(.*?)</span></td><td class="wrap-normal">'
$aArray = StringRegExp($sHTML, $sPattern, 3)
$oForm = _IEFormGetObjByName($oIE, 'maform')
;~ _ArrayDisplay($aArray)
For $i = 0 To UBound($aArray) - 1 Step 2
;~ ConsoleWrite($sPrefixe & $aArray[$i] & $sSuffixe & @CRLF)
$res = _IEFormElementCheckBoxSelect($oForm, 0, $sPrefixe & $aArray[$i] & $sSuffixe, -1, "byIndex")
If @error Then Exit MsgBox($MB_SYSTEMMODAL + $MB_ICONERROR, '', 'Erreur ' & @error & ' (' & $aArray[$i] & ')')
;If $res = 1 Then FileWrite($hFile, $aArray[$i + 1] & @CRLF)
If $res = 1 Then ConsoleWrite($aArray[$i + 1] & @CRLF)
Next
Next
Re: [..] Erreur suite à saturation mémoire ?
Posté : ven. 24 juin 2016 09:47
par jpascal
Je te remercie d'avoir pris de ton temps pour tester.
Je n'ai pas d'erreur si j'utilise ton script et mon code épuré (j'ai modifié le premier $i en $j pour que la boucle fonctionne).
J'ai bien peur que cela soit la structure du site et les javascripts intégrés qui posent problème.
J'ai en effet un message qui apparaît au bout d'un certain temps qui me déconnecte du site.
De plus la page est insérée dans plusieurs cadres.
Un code plus complet pour voir comment je procède :
Code : Tout sélectionner
ProgressOn($g_eTitleApp, 'Récupération des tâches', '', Default, Default, $DLG_MOVEABLE)
Local $iLines = UBound($g_aLines) - 1
For $i = $ibegin To $iLines Step 2
;ConsoleWrite($g_aLines[$i] & @CRLF)
$res = _IEFormElementCheckBoxSelect($g_oForm, 0, $ePrefixe & $g_aLines[$i] & $eSuffixe, -1, "byIndex")
If @error Then
ConsoleWrite('Erreur on line ' & $i & @CRLF)
ReloadContent()
Sleep(3000)
$res = _IEFormElementCheckBoxSelect($g_oForm, 0, $ePrefixe & $g_aLines[$i] & $eSuffixe, -1, "byIndex")
If @error Then
ProgressOff()
FileDelete($eFileResume)
FileWrite($eFileResume, $i)
MsgBox($MB_SYSTEMMODAL + $MB_ICONERROR, $g_eTitleApp, 'Erreur sur la tâche ' & $g_aLines[$i] & ' :' & @CRLF & $g_aLines[$i + 1] & @CRLF & @CRLF & 'Veuillez relancer le programme.')
Exit
EndIf
EndIf
ProgressSet($i * 100 / $iLines, 'Tâche ' & $g_aLines[$i] & ' / ' & $g_aLines[$iLines - 1])
If $res = 1 Then FileWrite($hFile, $g_aLines[$i + 1] & @CRLF)
;Sleep(100)
Next
ProgressOff()
Code : Tout sélectionner
Func ReloadContent()
Local $oFrame0 = _IEFrameGetCollection($g_oIE, 0)
If @error Then Exit MsgBox($MB_SYSTEMMODAL + $MB_ICONERROR, $g_eTitleApp, 'Erreur de récupération du cadre 0 (' & @error & ')')
Local $oFrame1 = _IEFrameGetCollection($oFrame0, 0)
If @error Then Exit MsgBox($MB_SYSTEMMODAL + $MB_ICONERROR, $g_eTitleApp, 'Erreur de récupération du cadre 1 (' & @error & ')')
Local $oFrame = _IEFrameGetCollection($oFrame1, 1)
If @error Then Exit MsgBox($MB_SYSTEMMODAL + $MB_ICONERROR, $g_eTitleApp, 'Erreur de récupération du cadre (' & @error & ')')
$g_oForm = _IEFormGetCollection($oFrame, 0)
If @error Then Exit MsgBox($MB_SYSTEMMODAL + $MB_ICONERROR, $g_eTitleApp, 'Erreur de récupération du formulaire (' & @error & ')')
$g_oSelect = _IEFormElementGetObjByName($g_oForm, "m$c$gridTasks$p$drpPageSize")
If @error Then Exit MsgBox($MB_SYSTEMMODAL + $MB_ICONERROR, $g_eTitleApp, 'Erreur de récupération de la liste déroulante (' & @error & ')')
Local $sHTML = _IEBodyReadHTML($oFrame)
If @Compiled = 0 Then
FileDelete('_debug' & $g_iDebug & '.htm')
FileWrite('_debug' & $g_iDebug & '.htm', $sHTML)
$g_iDebug += 1
EndIf
$sPattern = '<label for="' & $ePrefixe & '(\d+)' & $eSuffixe & '">.*?onmouseout="UnTip\(\)">(.*?)</span></td><td class="wrap-normal">'
$g_aLines = StringRegExp($sHTML, $sPattern, 3)
If @error <> 0 Then Exit MsgBox($MB_SYSTEMMODAL + $MB_ICONERROR, $g_eTitleApp, "Le code du site a changé.")
EndFunc ;==>ReloadContent
J'ai rajouté FileWrite('_debug' & $g_iDebug & '.htm', $sHTML) de manière à conserver le code source après chaque ReloadContent.
C'est systématique.
Soit le programme récupère les checkbox SANS ERREUR.
Soit j'obtiens une erreur, le prog récupère le code HTML, j'obtiens une seconde erreur, le prog récupère le code HTML, mais impossible de récupérer l'état des checkbox suivantes.
J'ai comparé les 3 fichiers (avant erreur, après première erreur, après seconde erreur), le code est identique.
Re: [..] Erreur suite à saturation mémoire ?
Posté : ven. 24 juin 2016 16:11
par orax
Il n'y a pas besoin de récupérer le code HTML, on pourrait aussi faire comme ça :
Code : Tout sélectionner
#include <IE.au3>
$sURL = 'http://au3.96.lt/temp/prob_autoit.html'
$oIE = _IECreate($sURL)
;~ $oIE = _IEAttach('prob_autoit.html', 'url')
Sleep(10000) ; le temps de cocher des cases
$oInputs = $oIE.document.getElementsByTagName("input")
For $oInput In $oInputs
If $oInput.checked Then
$oSpan = $oInput.parentElement.parentElement.parentElement.getElementsByTagName('span').item(4)
If IsObj($oSpan) Then
ConsoleWrite($oInput.id & " - nom de la tâche : " & $oSpan.textContent & @CRLF)
EndIf
EndIf
Next
Dans cet exemple, on navigue dans le DOM pour trouver les éléments.
Quand on est au niveau du l'INPUT, on remonte au TR (avec les parentElement) pour rechercher, dans les éléments enfants, le SPAN qui contient le nom de la tâche.
Re: [..] Erreur suite à saturation mémoire ?
Posté : ven. 24 juin 2016 17:35
par jpascal
Quelle bonne idée. Comme quoi les habitudes c'est mal.
J'utilisais le DOM pour les scripts GreaseMonkey mais jamais dans AutoIt.
J'essaierai la semaine prochaine et je ferai un retour pour voir si c'est mieux.
Merci.
Re: [..] Erreur suite à saturation mémoire ?
Posté : ven. 24 juin 2016 18:39
par orax
En fait, je ne t'apprends sans doute rien, mais c'est ce que font les fonctions _IE*. D'ailleurs, dans mon code, getElementsByTagName
aurait pu être remplacé par _IETagNameGetCollection
.
Re: [..] Erreur suite à saturation mémoire ?
Posté : mar. 28 juin 2016 09:46
par jpascal
Bonjour orax,
Détrompe-toi, je ne le savais pas. J'avoue ne pas avoir eu la curiosité d'aller regarder le code de l'UDF.
Et bien c'est magniiiiifiiiique ! Le traitement prend une seconde désormais contre plus d'une minute auparavant (sans compter le fait de devoir relancer le programme).
Un grand merci à toi.