Что нового

Реализация подобия SEH в AutoIt - Обработка ошибок

firex

AutoIT Гуру
Сообщения
943
Репутация
205
AutoIt: 3.3.12.0, 3.3.9.4, 3.3.8.X, 3.3.6.X
Версия: 0.2.2

Категория: Вспомогательные функции

Описание: Добавляет возможность регистрирования Callback-функции вызываемой в момент обнаружения ошибки при выполнении скомпилированного скрипта. Позволяет проигнорировать ошибку и продолжить выполнение.

Список функций:
Код:
; #CURRENT#
; OnAutoItErrorRegister( [ $sFunc ] )
; OnAutoItErrorUnRegister()

Пример:
Код:
#Include <SEH.au3>
OnAutoItErrorRegister( '__Example_OnError' ) ; >>> __TRY {
	For $Idx = 1 To 5 Step 1
		$PlsError[1] = $PlsError[2]
	Next
OnAutoItErrorUnRegister() ; >>> }

Func __Example_OnError( $pErrMsg ) ; >>> __EXCEPT {
	Local $tError, $aRes
	; *
	$aRes = DllCall("kernel32.dll", "int", "lstrlenW", "ptr", $pErrMsg)
	If @Error Or Not $aRes[0] Then _
		Return 0 ;Terminate script

	$tError = DllStructCreate( "wchar Msg[" & $aRes[0] & "]", $pErrMsg )
	If @Error Then _
		Return 0 ;Terminate script
	; ---

	If MsgBox( 5, 'Custom Au3Error callback', DllStructGetData( $tError, 'Msg' ) ) = 2 Then _
		Return 0 ;Terminate script

	; ---
	Return 1 ;Continue execute
EndFunc ; >>> }

Файлы: SEH.au3, SEH_beta.au3
(с форума можно будет качать только release-версии)

Лог обновлений:
Код:
[0.3.3](beta) - 14.02.15
{+} Попытка заставить работать переход к указанной строке для всех типов исключений

[0.3.2](beta) - 14.02.15
{*} Переименованы функции ( __TRY / __ENDTRY )
{*} Изменен формат возвращаемого значения ( < 0; = 0; > 0 ) 
{+} Экспериментальная* возможность перехода к указанной строке для блока __TRY( и за его пределы )
* - (Временно поддерживаются не все типы исключений)

[0.3.0](beta) - 11.02.15
{-} Поддержка только 3.3.12.0 (x86) - временно
{+} Поддержка интерпретируемой версии(Run script).
{+} Захват ошибок с флагом /ErrorStdOut
{+} Все данные распределены по аргументам обработчика (pwError, pwScriptLine, iLine)
{+} Получение реального номера строки (см. SEH_INCLUDES_LENGTH)*
{+} Получение** строки скрипта (в которой произошло исключение)
* - (библиотека SEH.au3 должна быть подключена после других)
** - (только для не скомпилированной версии)

[0.2.2] - 08.02.15
{+} Поддержка 3.3.9.4, 3.3.8.X, 3.3.6.X
{+} Обработка ошибок
{+} Продолжение/остановка выполнения скрипта

[0.0.1] - 07.02.15
{+} Игнорирование ошибок

Источник: autoit-script.ru
Автор(ы): Firex
 

inververs

AutoIT Гуру
Сообщения
2 135
Репутация
464
Для нескомпенсированного скрипта еще бы такую функцию.
 
Автор
firex

firex

AutoIT Гуру
Сообщения
943
Репутация
205
inververs
Посмотрю, что можно сделать.
 

madmasles

Модератор
Глобальный модератор
Сообщения
7 790
Репутация
2 319
firex,
Скомпилировал Ваш пример, запустил, получил сообщение:
Код:
Line 42  (File "C:\Users\...\Desktop\AutoIt v3 Script (9).exe"):


Error: Expected a "=" operator in assignment statement.
Но можно как-то узнать, что ошибка именно в строке $PlsError[1] = $PlsError[2]?
 
Автор
firex

firex

AutoIT Гуру
Сообщения
943
Репутация
205
madmasles
Проблематично будет. Единственное, что я могу предусмотреть в будущем - относительный переход ( ибо это просчитываемо ), а вот на счет идентификации реального номера строки придется подумать. Проблема в том, что AutoIt при компиляции "склеивает" библиотеки ( Include ) и основной скрипт.

Если вы собираетесь использовать только SEH, то высчитать строку можно путем вычитания кол-ва строк из библиотеки SEH. Иначе - придется вычитать кол-во строк из всех библиотек.

Upd/
Если вы имеете ввиду текст самой строки, то посмотрю, что можно сделать. Полагаю это возможно, хоть и отключено в скомпилированной версии.
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 473
Репутация
2 403
firex [?]
Если вы собираетесь использовать только SEH, то высчитать строку можно путем вычитания кол-ва строк из библиотеки SEH. Иначе - придется вычитать кол-во строк из всех библиотек.
А если сделать условием указания этой библиотеки в самом конце списка библиотек, то наверняка можно вычислить позицию её начала и считать уже от неё?
 
Автор
firex

firex

AutoIT Гуру
Сообщения
943
Репутация
205
CreatoR [?]
А если сделать условием указания этой библиотеки в самом конце списка библиотек, то наверняка можно вычислить позицию её начала и считать уже от неё?
Единственное, что приходит в голову ( при условии, что SEH указана последней ):
-Добавляем в библиотеку строку, к примеру #SEH
-Пишем скрипт под AutoIt3Wrapper, который между этапами обработки и компиляции вычислит номер строки #SEH и создаст в шапке скрипта константу.

Еще вариант:
-Создать преднамеренное исключение и перехватить его в библиотечном обработчике.

Подумаю еще, полагаю найдется более оптимальный способ.
 

inververs

AutoIT Гуру
Сообщения
2 135
Репутация
464
firex [?]
Подумаю еще, полагаю найдется более оптимальный способ.
Да не особо нужно правильно высчитывать номер строки, гораздо важнее это показывать вот это:

$PlsError[1] = $PlsError[2]
$PlsError^ ERROR

Error: Expected a "=" operator in assignment statement.
По этому выражению легко найти место в скриптах. А номер строки даже если и знать, то не ясно в каком include ее смотреть.
 
Автор
firex

firex

AutoIT Гуру
Сообщения
943
Репутация
205
Небольшое обновление, список изменений добавил в лог.

На счет получения строки скрипта в скомпилированной версии: пока не в приоритете, слишком много кода придется перелопатить.
 

joiner

Модератор
Локальный модератор
Сообщения
3 362
Репутация
586
запускал пример с бета-версией библиотеки. никаких сообщений об ошибке в коде
код использовал из первого сообщения



Добавлено:
Сообщение автоматически объединено:

помимо этого в бетке есть ошибка
Код:
Func __SEH_GetIncludesLength()
        If OnAutoItErrorRegister( '__SEH_InternalCb' ) Then
                SEH_GetError  ; тут

                OnAutoItErrorUnRegister()
        EndIf
EndFunc
 
Автор
firex

firex

AutoIT Гуру
Сообщения
943
Репутация
205
joiner
Убедитесь, что запускаете на x86 версии. Проверил еще раз - все работает.

Для запуска из под редактора можете использовать:
Код:
#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Run_AU3Check=n
#AutoIt3Wrapper_Tidy_Stop_OnError=n
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****


На счет ошибки - так и должно быть.
 

joiner

Модератор
Локальный модератор
Сообщения
3 362
Репутация
586
насчет ошибки можешь пояснить почему так? интересно
запускаю на семерке х86, версия autoit - последняя стабильная
не бетка работает нормально


Добавлено:
Сообщение автоматически объединено:

что пишет редактор в логе
Код:
>Running:(3.3.12.0):C:\Program Files\AutoIt3\autoit3.exe "C:\Users\master\Desktop\Rate.au3"    
--> Press Ctrl+Alt+Break to Restart or Ctrl+Break to Stop
!>10:56:56 AutoIt3.exe ended.rc:-1073741819
+>10:56:56 AutoIt3Wrapper Finished.
>Exit code: 3221225477    Time: 8.228
 
Автор
firex

firex

AutoIT Гуру
Сообщения
943
Репутация
205
joiner [?]
насчет ошибки можешь пояснить почему так? интересно
Таким образом происходит получение размера всех подключенных библиотек в скрипт => позволяет получить верную строку ошибки в основном скрипте ( если он скомпилирован ).

запускаю на семерке х86, версия autoit - последняя стабильнаяне бетка работает нормально
Вы брали пример из новой беты? Поменялись аргументы callback функции. Пример к бете включен в шапку UDF.
 

joiner

Модератор
Локальный модератор
Сообщения
3 362
Репутация
586
да точно. не тот пример :smile:
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 473
Репутация
2 403
Номер строки неправильный если использовать директивы AutoItWrapper.
 
Автор
firex

firex

AutoIT Гуру
Сообщения
943
Репутация
205
Обновление до 0.3.2(beta). Изменения/добавления занесены в лог.

Пример к новой (beta) как обычно в шапке UDF(beta).
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 473
Репутация
2 403
firex
Как можно найти нужные адреса для добавления поддержки других версии AutoIt?
Какой алгоритм поиска?

И ещё, можно как то добавить определение ошибки "Recursion level has been exceeded"?
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 473
Репутация
2 403
И ещё, я считаю что в конечном варианте (законченный продукт), пользователю незачем отображать строку кода с ошибкой. Вместо этого, сам разработчик (получив скрин или данные ошибки) может вычислить строку ошибки используя мой стрипер (также прикрепил).
 

Вложения

Автор
firex

firex

AutoIT Гуру
Сообщения
943
Репутация
205
CreatoR [?]
Как можно найти нужные адреса для добавления поддержки других версии AutoIt?Какой алгоритм поиска?
Можно достаточно быстро выйти на обработчик путем поиска обращений к уникальной строке: "Line %d (File "%s"):" Их(обработчика) должно быть два, один выводит инфу в консоль, а второй в MessageBox. Предупрежу: они практически идентичны, без понятия зачем разработчики проделали такой копипаст.

Его начало - это в основном сбор информации об ошибке / некоторые проверки, затем вызов MessageBoxW и сразу же CleanUp-процедуры. Я перезаписывал этот регион памяти своим кодом, который вызывает установленный CallBack с некоторой информацией.

И ещё, можно как то добавить определение ошибки "Recursion level has been exceeded"?
Перепроверил - действительно, скрипт падает. На максимальном значении вложенности скрипт вызывает ошибку, однако библиотека перехватывает ее и кидает управление на CallBack, именно это вызывает переполнение стека и падение скрипта - еще один вызов функции как никак.

Можно поправить уменьшив лимит, но это не защитит глупого пользователя от рекурсии в обработчике ошибки связанной с рекурсией :smile:

И ещё, я считаю что в конечном варианте (законченный продукт), пользователю незачем отображать строку кода с ошибкой. Вместо этого, сам разработчик (получив скрин или данные ошибки) может вычислить строку ошибки используя мой стрипер (также прикрепил).
В BETA я разделил по разным аргументам текст и номер строки, но она сыра и не портирована под другие версии.

Быть может позже руки дойдут...
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 473
Репутация
2 403
firex [?]
Можно достаточно быстро выйти на обработчик путем поиска обращений к уникальной строке: "Line %d (File "%s"):"
Можно небольшую инструкцию как это корректно сделать? Очень хотелось бы покопаться в этом чтобы прикрутить и другие версии, а также чтобы оно работало и не в скомпилированном скрипте.
 
Верх