Что нового

Оптимальный выбор проверки возвращения результатов функций AutoIT

---Zak---

Скриптер
Сообщения
455
Репутация
120
Добрый день всем.

Сидел тут и думал...думал... а потом БАХ :idea: !!! И начал думать уже о другом, а точнее задался вопросом каким способом оптимальнее всего проверять возвращение результатов различных функций AutoIT :IL_AutoIt_1: - пусть уже стандартных.

В общем подробнее будет на примерах:


Допустим мы используем команду
Код:
Run("notepad.exe", "", @SW_HIDE)

По справке у нас возвращает:
Return Value
Success: the PID of the process that was launched.
Failure: 0 and sets the @error flag to non-zero.
Все здорово - но иногда даже для такой команды стоит проверить на наличии ошибки в запуске функции (допустим мы ошиблись в запуске файла и/или такого файла не существует)

Вот три варианта, которые мне пришли в голову:
Код:
;~ ////////////////////////////////////////////////
ConsoleWrite(';~ ////////////////////////////////////////////////'&@CRLF)
ConsoleWrite(@TAB&'Run("notepad.exe", "", @SW_HIDE) === Success: the PID of the process'&@CRLF)
ConsoleWrite(';~ ////////////////////////////////////////////////'&@CRLF)
;~ ////////////////////////////////////////////////
$iPID = Run("notepad.exe", "", @SW_HIDE)
If @error Then
    ConsoleWrite('If @error Then - ERROR !!!'&@CRLF)
Else
	ConsoleWrite('+If @error Then - NOT error !!! - GOOD !!!'&@CRLF)
EndIf
	Sleep(500)
ProcessClose("notepad.exe")

$iPID = Run("notepad.exe", "", @SW_HIDE)
If $iPID Then
    ConsoleWrite('+If $iPID Then - TRUE - GOOD !!!'&@CRLF)
Else
	ConsoleWrite('If $iPID Then - FALSE'&@CRLF)
EndIf
	Sleep(500)
ProcessClose("notepad.exe")

If Run("notepad.exe", "", @SW_HIDE) Then
    ConsoleWrite('+If Run("notepad.exe", "", @SW_SHOWMAXIMIZED) Then - TRUE - GOOD !!!'&@CRLF)
Else
	ConsoleWrite('If Run("notepad.exe", "", @SW_SHOWMAXIMIZED) Then - FALSE'&@CRLF)
EndIf
	Sleep(500)
ProcessClose("notepad.exe")

В "консоли" мы получи следующее:
;~ ////////////////////////////////////////////////
Run("notepad.exe", "", @SW_HIDE) === Success: the PID of the process
;~ ////////////////////////////////////////////////
+If @error Then - NOT error !!! - GOOD !!!
+If $iPID Then - TRUE - GOOD !!!
+If Run("notepad.exe", "", @SW_SHOWMAXIMIZED) Then - TRUE - GOOD !!!

ЗЫ: где выделенно зеленым цветом - на мой взгляд я считаю верным ответом на условие.
ЗЫЫ: в данном примере все условия буду работать правильно, т.к. "Failure" вернет 0 и "установит" @error.



В случае, если мы указали на запуск НЕ верный файлы (файла такого нет)
;~ ////////////////////////////////////////////////
Run("notepad1.exe", "", @SW_HIDE) === Success: the PID of the process
;~ ////////////////////////////////////////////////
If @error Then - ERROR !!!
If $iPID Then - FALSE
If Run("notepad.exe", "", @SW_SHOWMAXIMIZED) Then - FALSE


Теперь предлагаю посмотреть на следующий пример:

ЗЫ: notepad.exe - НЕ запущен !!!
Код:
ProcessExists("notepad.exe")

возвращает:
Return Value
Success: the PID of the process.
Failure: 0 if process does not exist.

3 условия на проверку:
Код:
;~ ////////////////////////////////////////////////
ConsoleWrite(';~ ////////////////////////////////////////////////'&@CRLF)
ConsoleWrite(@TAB&'ProcessExists("notepad.exe") === Success: the PID of the process. '&@CRLF)
ConsoleWrite(';~ ////////////////////////////////////////////////'&@CRLF)
;~ ////////////////////////////////////////////////
$iPID = ProcessExists("notepad.exe")
If @error Then
    ConsoleWrite('+If @error Then - ERROR !!! - GOOD !!!'&@CRLF)
Else
	ConsoleWrite('If @error Then - NOT error !!!'&@CRLF)
EndIf

$iPID = ProcessExists("notepad.exe")
If $iPID Then
    ConsoleWrite('If $iPID Then - TRUE'&@CRLF)
Else
	ConsoleWrite('+If $iPID Then - FALSE - GOOD !!!'&@CRLF)
EndIf

If ProcessExists("notepad.exe") Then
    ConsoleWrite('If ProcessExists("notepad.exe") Then - TRUE'&@CRLF)
Else
	ConsoleWrite('+If ProcessExists("notepad.exe") Then - FALSE - GOOD !!!'&@CRLF)
EndIf

Итог примера:
;~ ////////////////////////////////////////////////
ProcessExists("notepad.exe") === Success: the PID of the process.
;~ ////////////////////////////////////////////////
If @error Then - NOT error !!!
+If $iPID Then - FALSE - GOOD !!!
+If ProcessExists("notepad.exe") Then - FALSE - GOOD !!!

Здесь Мы с Вами видим, что @error уже НЕ "отработало", а точнее "Failure" установит исключительно свой параметр, но не "поставит ошибку". Т.е. у Нас отработало только 2 и 3 вариант проверки, в отличии от первого примера, в котором все 3 варианта проверки увенчались успехом.


И напоследок для сравнения 3 пример:

ЗЫ: но "папки" предположим такой НЕ существует !!!
Код:
DirGetSize(@ScriptDir&"QWE")


Что возвращает:
Return Value
Success: the sizes that are greater than or equal to zero
Failure: -1 and sets the @error flag to 1 if the path doesn't exist.



Очередные 3 варианта проверки:
Код:
;~ ////////////////////////////////////////////////
ConsoleWrite(';~ ////////////////////////////////////////////////'&@CRLF)
ConsoleWrite(@TAB&'DirGetSize(@ScriptDir&"QWE") === Success: the sizes that are greater than or equal to zero'&@CRLF)
ConsoleWrite(@TAB&'FileExists (@ScriptDir&"QWE") === '&FileExists (@ScriptDir&'QWE')&' !!! (Failure: 0 if path/file does not exist.)'&@CRLF)

ConsoleWrite(';~ ////////////////////////////////////////////////'&@CRLF)
;~ ////////////////////////////////////////////////
$vSize = DirGetSize(@ScriptDir&'QWE')
If @error Then
    ConsoleWrite('+If @error Then - ERROR !!! - GOOD !!!'&@CRLF)
Else
	ConsoleWrite('If @error Then - NOT error !!!'&@CRLF)
EndIf

$vSize = DirGetSize(@ScriptDir&'QWE')
If $vSize Then
    ConsoleWrite('If $vSize Then - TRUE'&@CRLF)
Else
	ConsoleWrite('+If $vSize Then - FALSE - GOOD !!!'&@CRLF)
EndIf

If DirGetSize(@ScriptDir&'QWE') Then
    ConsoleWrite('If DirGetSize(@ScriptDir&"QWE") Then - TRUE'&@CRLF)
Else
	ConsoleWrite('+If DirGetSize(@ScriptDir&"QWE") Then - FALSE - GOOD !!!'&@CRLF)
EndIf

Итог:
;~ ////////////////////////////////////////////////
DirGetSize(@ScriptDir&"QWE") === Success: the sizes that are greater than or equal to zero
FileExists (@ScriptDir&"QWE") === 0 !!! (Failure: 0 if path/file does not exist.)
;~ ////////////////////////////////////////////////
+If @error Then - ERROR !!! - GOOD !!!
If $vSize Then - TRUE
If DirGetSize(@ScriptDir&"QWE") Then - TRUE

Ну что я хочу скачать: исключительный случай, в котором сработал только 1 вариант - параметр в "Failure" возвращает не "0", а "-1". Оператор "IF" его можно сказать "съел", но вот @error здесь выше всех похвал.


И тут я задумался о ГЛАВНОМ: если по сути у всех функций написан разный функционал - кто-то возвращает все три параметра, у кто-то не сработывает @error, а у кого-то наоборот.

Теперь хотелось бы поинтересоваться у Вас - а каким способом Вы проверяете возвращение функций ??? Я не думаю, что каждый раз Вы лезете в справку и смотрите что должно быть в таком случае.
 

firex

AutoIT Гуру
Сообщения
943
Репутация
208
---Zak--- [?]
Теперь хотелось бы поинтересоваться у Вас - а каким способом Вы проверяете возвращение функций
huh.gif
Я не думаю, что каждый раз Вы лезете в справку и смотрите что должно быть в таком случае.
Да если честно не задавался этим вопросом, почти все уже запомнилось.
 
Автор
---Zak---

---Zak---

Скриптер
Сообщения
455
Репутация
120
firex
В справке более 350 функций - отделаться одним "все уже запоснилось"... ну даже не знаю.

Ну если пользоваться одними и теми же, то да - я не спорю запомнить можно. Хотя и то - наткнуться можно,а не хотелось бы !!!

ЗЫ: я сам не задавался, но как-то так нагрянуло после праздника то :beer:.
 

sims

Осваивающий
Сообщения
184
Репутация
24
---Zak--- [?]
Ну что я хочу скачать: исключительный случай, в котором сработал только 1 вариант - параметр в "Failure" возвращает не "0", а "-1". Оператор "IF" его можно сказать "съел"
Это вы читать не умеете (и не знаете как работает If). Там же на чистом русском написано что в случае успешного выполнения вернет 0 или больше. А у вас что в условии? Оно справедливо если не ноль!
Должно быть.
Код:
;~ ////////////////////////////////////////////////
ConsoleWrite(';~ ////////////////////////////////////////////////'&@CRLF)
ConsoleWrite(@TAB&'DirGetSize(@ScriptDir&"QWE") === Success: the sizes that are greater than or equal to zero'&@CRLF)
ConsoleWrite(@TAB&'FileExists (@ScriptDir&"QWE") === '&FileExists (@ScriptDir&'QWE')&' !!! (Failure: 0 if path/file does not exist.)'&@CRLF)

ConsoleWrite(';~ ////////////////////////////////////////////////'&@CRLF)
;~ ////////////////////////////////////////////////
$vSize = DirGetSize(@ScriptDir&'QWE')
If @error Then
    ConsoleWrite('+If @error Then - ERROR !!! - GOOD !!!'&@CRLF)
Else
    ConsoleWrite('If @error Then - NOT error !!!'&@CRLF)
EndIf

$vSize = DirGetSize(@ScriptDir&'QWE')
If $vSize >=0 Then
    ConsoleWrite('If $vSize Then - TRUE'&@CRLF)
Else
    ConsoleWrite('+If $vSize Then - FALSE - GOOD !!!'&@CRLF)
EndIf

If DirGetSize(@ScriptDir&'QWE') >=0 Then
    ConsoleWrite('If DirGetSize(@ScriptDir&"QWE") Then - TRUE'&@CRLF)
Else
    ConsoleWrite('+If DirGetSize(@ScriptDir&"QWE") Then - FALSE - GOOD !!!'&@CRLF)
EndIf
 

firex

AutoIT Гуру
Сообщения
943
Репутация
208
---Zak--- [?]
В справке более 350 функций - отделаться одним "все уже запоснилось"... ну даже не знаю.
Я имел ввиду стандартные, а UDF лишь которые использую часто, иначе - справка(хотя в большинстве случаев из описания в Scite интуитивно понятно что возвращает функция).

Флаг Error(если требуется) - опять же справка.
 
Автор
---Zak---

---Zak---

Скриптер
Сообщения
455
Репутация
120
sims
Скорее всего Вы поставили не совсем корректное предложение: Это вы читать не умеете (и не знаете как работает If).
ЗЫ: на мой взгля IF тут совершенно не причем, но мне нравится ход Ваших мыслей !!! Спасибо за чтение материала и отзыва обо мне.

Скорее всего Вы имели в виду о
Код:
DirGetSize

Именна ЭТА ФУНКЦИЯ возвращает что-либо, а не оператор IF нам необоходимо указать ">=0". Т.е. тут еще есть и другие варианты.

Спасибо sims за поправку !!!


А вот чтобы проверить "DirGetSize" через "IF" (при условии, что такой папки НЕ существует) - нужно
Код:
If DirGetSize("path") >=0 Then

:scratch:

firex
Да, но на примере
Код:
ProcessExists


Он не возвращает @error
 

firex

AutoIT Гуру
Сообщения
943
Репутация
208
---Zak---
И все же если есть проблема - то достаточно попросту сделать так:

Код:
$vResult = Function()
If $vResult Then


В AutoIt при успешном выполнении все стандартные функции возвращают результат отличный от 0 и False. (кроме конечно Execute, Opt и тому подобных).
 

sims

Осваивающий
Сообщения
184
Репутация
24
---Zak--- [?]
на мой взгля IF тут совершенно не причем
Плохой вы программист если не знаете элементарных вещей, таких как работа оператора If.
По вашему это условие
Код:
If $vSize Then
верно если число в $vSize больше или равно 0, и неверно если -1? Если да, то почему?
 
Автор
---Zak---

---Zak---

Скриптер
Сообщения
455
Репутация
120
firex
Код:
DirGetSize

возвращает 0...

Но суть я понял - тогда буду придерживаться этого мнения. Спасибо.
Хотелось бы однообразия - если ошибка, то во всех случаях вызавал @error.

sims
Эммм... скорее всего Вы правы - я отвратительный программист и многое в этом мире не знаю, но суть моей темы была далека от ВАШЕЙ МЫСЛИ.
ЗЫ: скажу по секрету я не каждый раз заглядываю в справку и "Что функция возвращает нам НЕ известно", но со слов firex, в отличии от Ваших: "вы читать не умеете"/"Плохой вы программист" - мне стало намного спокойнее.

Если Вы еще не поняли или может пропустили несколько моих букв - лично я НЕ каждый раз смотрю в справку и МНЕ с сегодняшнего дня стало значительнее интереснее что же функция возвращает.

Я согласен был бы, если "DirGetSize" вернул "0" при условии, что такая папка существует, но ее нет... Все... совсем Вы меня запутали с "DirGetSize"
ЗЫЫ: еще раз повторюсь - я не каждый раз смотрю в справку и до сегодняшнего момента ОСОБОГО значения не представлял что там возвращает. Я знаю, что функция вернет или 0 или ошибку или еще что. Но запоминать что какая функция вернет в том или ином варианте нет особого желания.
 

sims

Осваивающий
Сообщения
184
Репутация
24
Код:
$x=1
if $x Then
	MsgBox(0, "", "1", 0)
EndIf

$x=0
if $x Then
	MsgBox(0, "", "0", 0)
EndIf

$x=-1
if $x Then
	MsgBox(0, "", "-1", 0)
EndIf
 
Автор
---Zak---

---Zak---

Скриптер
Сообщения
455
Репутация
120
sims
Товарищ по форуму - сделайте, пожалуйста, акцент/внимание на СУТЬ вопроса, а не то, как я решил проверить
Код:
DirGetSize

А так же не как я пользуюсь
Код:
If

ЗЫ: чтобы не флудить особо - отредактировал "Ответ #8"
ЗЫЫ: спасибо, что подправили с "DirGetSize"

Суть темы не в том, что и как я проверяю оператором IF, а как оптимально и с наименьшей вероятностью наткнуться на "косяк" в программировании (с учетом написания программ БЕЗ справки - ну или прибегнуть малую долю времени к ней).

Под фразой "косяк" - оптимальная проверка на ошибки в стандартных функциях

ЗЫ: это знаете, если бы я сейчас Вам написал о том, как Вы привели пример с
Код:
MsgBox(0, "", "1", 0)

С вопросом: зачем Вы в 4 параметре передаете "0", если по-умолчанию и так "0".

Без обид... :beer: С праздником.
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Чтобы понять, как действовать в случае ошибки, нужно ОБЯЗАТЕЛЬНО посмотреть описание соответствующей функции. Универсального способа нет и быть не может. Простой пример, DirGetSize(). Почему в случае ошибки эта функция возвращает -1, а не 0? Потому что размер папки может быть равен 0, а вот -1 нет. Даже в WinAPI ошибки проверяются по разному. Да и вчем проблема щелкнуть в редакторе на функцию и нажать F1?

А кроме того, в разных ситуациях ошибки удобнее проверять соответствующим способом. Например:

Код:
If ProcessExists(...) Then
	Exit
EndIf


Код:
$PID = ProcessExists(...)
If $PID Then
	ProcessSetPriority($PID, 4)
EndIf
 
Автор
---Zak---

---Zak---

Скриптер
Сообщения
455
Репутация
120
Yashied
Проблемы посмотреть в справку нет, но допустить вариант с изменением в возврашении "ошибки" стандартных функций не хотелось бы.

На текущий момент лично я считаю самым универсальным методом проверить на ошибку:
Код:
$vResult = Function()
If @error Then
	If $vResult Then
		MsgBox(0, '', 'ERROR')
	EndIf
EndIf


ЗЫ: а что если было бы - если каждая функция возвращала:
Failure: 0 and sets the @error flag to non-zero.
Функция "Run" же отрабатывает по всем проверкам...

Как бы вопрос (литорический) с интересом: почему "ProcessExists" - @error - пропускает "мимо ушей"

Простой пример, DirGetSize(). Почему в случае ошибки эта функция возвращает -1, а не 0? Потому что размер папки может быть равен 0, а вот -1 нет
Здесь я обеими руками ЗА !!! Полностью согласен, но так же вопрос в том - почему нет проверки: если такой паки НЕ существует он возвращает "0", а не False ???

Прошу прикрутить к DirGetSize() - в случае отсутствия папки прикрутить в ответ FALSE

Failure: 0 False and sets the @error flag to non-zero.
:beer:
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
Еще интересная функция
Код:
StringCompare
, не устанавливает ошибок, результат может быть 0, положительный или отрицательный. Поэтому нужно да, тыкать в справку и читать описание.


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

Всегда нужно сперва проверять макрос @error, а уже во вторую очередь возвращаемый результат.
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
---Zak--- сказал(а):
Прошу прикрутить к DirGetSize() - в случае отсутствия папки прикрутить в ответ FALSE

А чем False отличается от 0?

Код:
If False = 0 Then
	MsgBox(0, '', 'Эврика!!!')
EndIf
 
Автор
---Zak---

---Zak---

Скриптер
Сообщения
455
Репутация
120
inververs
Код:
StringCompare

Ну тут скорее всего проверка на длину строки... так что тут все гуд)))) Хотя если на длину - то причем тут регистр.


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

Yashied
))))) Да, согласен, не грамотный пример. Беру свои слова обратнос False... Эх...
Хотя я где-то у себя как "ошибку" передавал именно False, ну да ладно.
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
Еще из справки:
If a function can set the @error flag, you should always check it before using a return value - if @error indicates an error then the function return value is generally undefined...
Если функция может устанавливать @error флаг, то вы всегда должны сперва проверять его, а уже затем использовать возращаемое значение. Поэтому если установлен @error то возращаемое значение обычно не определено.
 
Автор
---Zak---

---Zak---

Скриптер
Сообщения
455
Репутация
120
Все... уговорили. Теперь пойду переделывать свои писанинки с "двойными" проверками на ошибки.

Всем спасибо за беседу... С прошедшим праздником... :IL_AutoIt_1:

sims
Извини, если что-то написал не так - просто как-то подхода к тебе не нашел, а точнее боялся потерять мысль об "ошибках". Надеюсь в дальнейшем еще увидимся на форуме, но уже по одну барикаду))))))
 
Верх