Что нового

ошибка в функции _IEBodyReadText()

valdur2000

Знающий
Сообщения
155
Репутация
7
вот кусочек кода:
Код:
$sURL = 'https://www.адрес.ru'
$oIE = _IECreate($sURL)
$hwnd = _IEPropertyGet($oIE, 'hwnd')
$oIE=_IEAttach($hwnd,"hwnd")
$oRng=_IEBodyReadText($oIE) ;тут фатальная ошибка с полным вылетом исполнения программы
If  @error = $_IEStatus_NoMatch Then
MsgBox(0,"","")
EndIf

вот его ошибка:
Код:
C:\Program Files\AutoIt3\Include\IE.au3 (1977) : ==> Variable must be of type "Object".:
Return SetError($_IEStatus_Success, 0, $o_object.document.body.innerText)
Return SetError($_IEStatus_Success, 0, $o_object.document.body^ ERROR

вот функция из библиотеки IE.au3 в которой происходит ошибка:
Код:
Func _IEBodyReadText(ByRef $o_object)
	If Not IsObj($o_object) Then
		__IEErrorNotify("Error", "_IEBodyReadText", "$_IEStatus_InvalidDataType")
		Return SetError($_IEStatus_InvalidDataType, 1, 0)
	EndIf
	If Not __IEIsObjType($o_object, "browserdom") Then
		__IEErrorNotify("Error", "_IEBodyReadText", "$_IEStatus_InvalidObjectType", "Expected document element")
		Return SetError($_IEStatus_InvalidObjectType, 1, 0)
	EndIf
	;
	Return SetError($_IEStatus_Success, 0, $o_object.document.body.innerText)
EndFunc   ;==>_IEBodyReadText


Раньше пользовал такой код:
Код:
$oRng = $oIE.document.body
i$oRng = $oRng.createTextRange()
     If	$oRng.findtext($error1) == True Then
     MsgBox(0,"","")
     EndIf

Ошибка была тут:
Код:
$oRng = $oIE.document.body


Описание проблемы: в IE заполняются тхт поля, потом жму на submit. если все успешно, то попадаю на след страничку с текстовым сообщением, которое пользуя $oRng=_IEBodyReadText($oIE) и обрабатываю. ошибка происходит непонятно когда. то через 20 циклов, то через 5, то бог знает когда. Помогите либо что-то исправить, уж не знаю даже где, либо у меня, либо в IE.au3 или ловить ошибку, чтобы не вылетала прога.
 

Garrett

Модератор
Локальный модератор
Сообщения
3,999
Репутация
967
Попробуйте продублировать ожидание загрузки страницы, функцией _IELoadWait
Код:
$sURL = 'https://www.адрес.ru'
$oIE = _IECreate($sURL)
_IELoadWait($oIE)
$oRng=_IEBodyReadText($oIE) ;тут фатальная ошибка с полным вылетом исполнения программы
If @error Then MsgBox(0, @ScriptName, @error)
 
Автор
V

valdur2000

Знающий
Сообщения
155
Репутация
7
IECreate на самом деле у меня далеко вверху.. Я подсократил код, что бы как бы нагляднее было... Рабочий кусок кода такой:
Код:
$oIE=_IEAttach($hwnd,"hwnd"); всегда ок
$title = WinGetTitle($hwnd)
If StringInStr($title,"Anmeldung Erfolg") Then 
ExitLoop
ElseIf StringInStr($title,"Meine Seite") Then
$oRng=_IEBodyReadText($oIE) ;тут фатальная ошибка с полным вылетом исполнения программы
;тут дальнейшие строки кода сравнивания текста полученной страницы и реакция на найденный текст.
EndIf

после $oRng=_IEBodyReadText($oIE) ставил и MsgBox и Consolewrite и If @error Then..
До этой строки не доходит. ошибка именно в IE.au3, там где показал... можно ли ошибку библиотеки перехватить?
 

Garrett

Модератор
Локальный модератор
Сообщения
3,999
Репутация
967
valdur2000 [?]
можно ли ошибку библиотеки перехватить?
Ошибка, указанная у вас в консоли Variable must be of type "Object" говорит о том, что у вас переменная $:shok:bject (она находится в UDF) не является объектом. Проще говоря у вас где-то в коде допущена ошибка вследствие чего переменная $oIE теряет статус (тип) объекта, и попадая в функцию
Код:
$oRng =_IEBodyReadText($oIE)
уже не является объектом.
 
Автор
V

valdur2000

Знающий
Сообщения
155
Репутация
7
Если б ошибка всегда выскакивала... а то, бывает через 5 бывает через 30 успешных циклов..
как я вас понял, мне надо после этой строки поставить проверку:
Код:
$oIE=_IEAttach($hwnd,"hwnd")

и в зависимости от результата двигаться дальше. если будет опять ошибка с успешным $oIE, то отпишусь. спасибо.
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
valdur2000
Можно поинтересоваться для чего вы делаете сперва
Код:
_IECreate
а затем делаете
Код:
_IEAttach
для одного и тогоже $oIE
 
Автор
V

valdur2000

Знающий
Сообщения
155
Репутация
7
Вначале я соответственно создаю окно, а потом там есть несколько дропдаунов, которые подгружают страницу в зависимости от выбранных данных. Раньше я пользовал IEAttach("слово", "titel"), а буквально на днях научился держать окно через PID. Может действительно уже IEAttach и не так важен.. А в данном примере я его показал, что что бы нагляднее было. вопрос относился именно к ошибке в $oRng=_IEBodyReadText($oIE)
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
У меня ошибка с _IEAttach была связано с тем, что не успевало полностью загрузиться окно IE. Пришлось делать WinWait. И _IEAttach использовать с параметром WindowTitle.

Еще я обратил внимание что _IELoadWait не всегда правильно дожидается.
Вместо этого я использую
Код:
sleep
плюс
Код:
_IEPropertyGet($oIE, "busy")
 
Автор
V

valdur2000

Знающий
Сообщения
155
Репутация
7
У меня два компа, на обоих семерки стоят. На компе с SciTE 1.79 не было ошибки ни разу за день. На компе с SciTE 2.28 вылет с ошибкой в IE.au3 каждые пол-часа.. IE.au3 в разных версиях по-ходу не совместимы.. Вот такое вот наблюдение...
 

vcomp71

Осваивающий
Сообщения
431
Репутация
25
Однозначно не успевает грузиться страница, в результате объект имеет пустое значение.
 
Автор
V

valdur2000

Знающий
Сообщения
155
Репутация
7
inververs спросил меня зачем я после $oIE=_IECreate и подцедпления процесса я еще $oIE=_IEAttach пользую. Я раньше цеплял стр по title и соответственно, если был переход на другую стр, то надо было аттачить заного, а с PID, как я понимаю, окнo остается всегда постоянным, пока стр не закроется.. Я конечно ставлю после каждого аттача проверку на ошибку, но нужен ли он вообще? может надо мне потереть все аттачи и оставить только IECreate? обилие IEAttach может привести к ошибкам или это чисто эстетическое нарушение, что код становится длиннее? В каких случаях надо по ходу выполнения программы аттачить страницу еще и еще?

Vlasssov: Однозначно не успевает грузиться страница, в результате объект имеет пустое значение.
Из справки: _IEBodyReadText($oIE) Returns the Text inside the <body> tag of the document. А как сделать проверку именно на то, что страничка загрузилась с <body> тэгами? и пока их нету, соответственно ждать.

inververs :_IEPropertyGet($oIE, "busy")
не совсем понял, как пользоваться и что должно произойти, но это проверка окна на занятость, а хочется проверять на наличие <body> тэга.
 

vcomp71

Осваивающий
Сообщения
431
Репутация
25
Вопрос, конечно, интересный... Честно говоря с таким не сталкивался, чтобы вот так прямо вылетало...

Может такую функцию для проверки попрбовать
Код:
IsObj

:scratch:
 

vcomp71

Осваивающий
Сообщения
431
Репутация
25
Что-то типа...
Код:
$sURL = 'https://www.адрес.ru'
$oIE = _IECreate($sURL)
$hwnd = _IEPropertyGet($oIE, 'hwnd')
$oIE=_IEAttach($hwnd,"hwnd")

While not(IsObj($oIE))
	Sleep 1
WEnd

$oRng=_IEBodyReadText($oIE) ;тут фатальная ошибка с полным вылетом исполнения программы
If  @error = $_IEStatus_NoMatch Then
MsgBox(0,"","")
EndIf
 
Автор
V

valdur2000

Знающий
Сообщения
155
Репутация
7
madmasles
Код:
IEErrorHandlerRegister()

А вы не могли бы, какой-то пример привести?
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
valdur2000 [?]
А вы не могли бы, какой-то пример привести?
Код:
#include <IE.au3>

Global $oIE, $fFlag, $iErrorNum = 0, $iSuccessNum = 0, $iStart

_IEErrorHandlerRegister()

$oIE = _IECreate('http://www.google.ru/')

HotKeySet('{Esc}', '_Exit')
AdlibRegister('_IEText', 1000)

$iStart = TimerInit()
While 1
	If TimerDiff($iStart) > 5000 Then
		$fFlag = Not $fFlag
		If $fFlag Then
			_IEExit()
		Else
			_IEOpen()
		EndIf
		$iStart = TimerInit()
	EndIf
	Sleep(100)
WEnd

Func _IEText()
	Local $s_Text, $s_TextIE = _IEBodyReadText($oIE)
	If $IEComErrorNumber Then
		$iErrorNum += 1
		$s_Text = 'Error: ' & $IEComErrorNumber
		$IEComErrorNumber = 0
	Else
		$iSuccessNum += 1
		$s_Text = 'Success'
		ConsoleWrite($s_TextIE & @LF)
	EndIf
	ToolTip($s_Text & @LF & 'Errors: ' & $iErrorNum & @LF & 'Successes: ' & $iSuccessNum, 0, 0)
EndFunc   ;==>_IEText

Func _IEExit()
	Local $h_Win = _IEPropertyGet($oIE, 'hwnd')
	If IsHWnd($h_Win) Then
		WinClose($h_Win)
	EndIf
EndFunc   ;==>_IEExit

Func _Exit()
	If IsObj($oIE) Then _IEQuit($oIE)
	Exit
EndFunc   ;==>_Exit

Func _IEOpen()
	$oIE = _IECreate('http://www.google.ru/')
EndFunc   ;==>_IEOpen
Или так.
Код:
#include <IE.au3>

Global $oIE, $fFlag, $iErrorNum = 0, $iSuccessNum = 0, $iStart

_IEErrorHandlerRegister('_IEError')

$oIE = _IECreate('http://www.google.ru/')

HotKeySet('{Esc}', '_Exit')
AdlibRegister('_IEText', 1000)

$iStart = TimerInit()
While 1
	If TimerDiff($iStart) > 5000 Then
		$fFlag = Not $fFlag
		If $fFlag Then
			_IEExit()
		Else
			_IEOpen()
		EndIf
		$iStart = TimerInit()
	EndIf
	Sleep(100)
WEnd

Func _IEError()
	SetError(1)
EndFunc   ;==>_IEError

Func _IEText()
	Local $s_Text, $s_TextIE = _IEBodyReadText($oIE)
	If @error Then
		$iErrorNum += 1
		$s_Text = 'Error'
	Else
		$iSuccessNum += 1
		$s_Text = 'Success'
		ConsoleWrite($s_TextIE & @LF)
	EndIf
	ToolTip($s_Text & @LF & 'Errors: ' & $iErrorNum & @LF & 'Successes: ' & $iSuccessNum, 0, 0)
EndFunc   ;==>_IEText

Func _IEExit()
	Local $h_Win = _IEPropertyGet($oIE, 'hwnd')
	If $h_Win Then
		WinClose($h_Win)
	EndIf
EndFunc   ;==>_IEExit

Func _Exit()
	If IsObj($oIE) Then _IEQuit($oIE)
	Exit
EndFunc   ;==>_Exit

Func _IEOpen()
	$oIE = _IECreate('http://www.google.ru/')
EndFunc   ;==>_IEOpen
 
Автор
V

valdur2000

Знающий
Сообщения
155
Репутация
7
я немного подсократил, и модифицировал. Свои функции никогда не писал, по-этому может быть где-то либо ошибка, либо непонимание что делать. Прошу подкорректировать...
Код:
#include <IE.au3>

_IEErrorHandlerRegister('_IEError'); это как я понял включение своего обработчика ошибок и если будет ошибка по ходу исполнения, то прога не вылетит, а вызовется _IEError() и установит @error=1. Объясните пожалуйста зачем? в первом варианте вы ничего с _IEErrorHandlerRegister не использовали... 
Func _IEError()
    SetError(1)
EndFunc   ;==>_IEError



Код:
Func _IEText();как я понял, эту функцию мне надо использовать перед всеми _IEBodyReadText($oIE)
    While 1
      $s_TextIE = _IEBodyReadText($oIE)
      If  Not @error Then
         ExitLoop
      Else
         sleep(1000)
      EndIf
    Wend
EndFunc   ;==>_IEText
[/autoit]

Пока в _IEBodyReadText($oIE) будет ошибка, While будет спать, по выходу из функции с неошибочным $s_TextIE, я продолжаю исполнение программы. Правильно ли я все понял?
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
valdur2000,
Дайте Вашу ссылку (можно в ЛС).

Попробуйте так.
Код:
#include <IE.au3>

$oIE = _IECreate('http://www.google.ru/', 0, 1, 0)

$sBody = _IEBodyReadTextEx($oIE)
If @error Then
	ConsoleWrite('Error' & @LF)
Else
	ConsoleWrite($sBody & @LF)
EndIf


Func _IEBodyReadTextEx($o_IE, $i_MaxTimeWait = 30000)
	Local $s_BodyTextIE, $iTimeStart

	If Not IsObj($oIEErrorHandler) Then _IEErrorHandlerRegister()
	$i_MaxTimeWait = Abs(Int($i_MaxTimeWait))
	If $i_MaxTimeWait < 1000 Then $i_MaxTimeWait = 1000
	$iTimeStart = TimerInit()
	While 1
		$s_BodyTextIE = _IEBodyReadText($o_IE)
		If $s_BodyTextIE Then ExitLoop
		If TimerDiff($iTimeStart) > $i_MaxTimeWait Then ExitLoop
		Sleep(500)
	WEnd
	If $s_BodyTextIE Then Return $s_BodyTextIE
	Return SetError(1, 0, '')
EndFunc   ;==>_IEBodyReadTextEx
 
Автор
V

valdur2000

Знающий
Сообщения
155
Репутация
7
madmasles
Все работает. огромное вам спасибо. Дней десять я искал решение. _IEErrorHandlerRegister - ловить критические ошибки, это ли не практически полное подчинение машины человеку? Отдельное спасибо от жены - я снова хорошо кушаю и сплю. Тема закрыта.
 
Верх