4. Рекомендуемая структура скрипта. Ошибки и отладка
Обработка ошибок в VBScript: самостоятельная работа
Упражнение 1. Обработка ошибок
Скопируйте на свой компьютер файл \Londontemplateserrors.vbs и откройте его в PrimalScript. Этот скрипт выполняет деление двух введенных вами чисел.
Реализуйте обработку ошибок таким образом, чтобы:
1) при значении второго числа, равного 0, пользователю выдавалось сообщение «Делить на ноль нельзя!» и приглашение ввести другое число;
2) если пользователь в любом из окон ввода нажал кнопку Cancel, выводилось повторное приглашение вести это число;
3) если пользователь ввел в любом из окон ввода строковое значение, выводилось сообщение «Нужно число» и повторное приглашение на ввод числа.
Код скрипта errors.vbs выглядит так:
Dim nNum1 Dim nNum2 Dim nResult
nNum1 = InputBox(«Введите первое число») nNum2 = InputBox(«Введите второе число»)
nResult = nNum1 / nNum2
MsgBox nResult,, «Результат деления»
Ответ к упражнению 1. Обработка ошибок
Задачу можно решить разными способами. Например, Microsoft в одном из учебных курсов предлагает такой вариант решения с вызовом функции из самой себя:
Dim nRes1, nAnwser
Select Case nRes1
MsgBox(«Деление на ноль!»)
nAnwser = MsgBox («Начать заново?», vbYesNo)
If nAnwser = vbYes Then
nAnwser = MsgBox (» Начатьзаново?», vbYesNo)
If nAnwser = vbYes Then
MsgBox(«Возникла неизвестная ошибка»)
nAnwser = MsgBox («Начать заново?», vbYesNo)
If nAnwser = vbYes Then
On Error Resume Next
Dim nNum2, nNum1, nResult
nNum1 = InputBox(» Введитепервоечисло«)
nNum2 = InputBox(«Введите второе число»)
Select Case Err.Number
Другой вариант решения – использовать цикл и обработку ошибок:
nNum1 = InputBox(«Введите первое число:»)
On Error Resume next
If Err.Number = 13 Then
On Error goto 0
nNum2 = InputBox(» Введитевтороечисло:»)
On Error Resume next
If Err.Number = 13 Then
Elseif nNum2 = 0 Then
MsgBox («Делить на ноль нельзя!»)
On Error goto 0
nResult = nNum1 / nNum2
MsgBox nResult,, «Результат деления: «
Третий вариант – самый лучший – вообще не допускает возникновения ошибок:
nNum1 = InputBox(» Введитепервоечисло: «)
If IsNumeric(nNum1 & «») Then Exit Do
MsgBox «Нужно число!»
nNum2 = InputBox(«Введите второе число: «)
If IsNumeric(nNum2 & «») Then
If Int(nNum2)<>0 Then Exit Do
MsgBox «Деление на ноль!»
MsgBox «Нужно число!»
nResult = nNum1 / nNum2
MsgBox nResult,, «Результат деления: «
Vbs скрипты ошибка
Сообщения: 25778 Благодарности: 7508
Err.Clear здесь лишнее — до On Error Resume Next все возникающие ошибки вызывают останов скрипта (и, возможно, вызов отладчика), а после On Error Resume Next никакой ошибки до Вашего Err.Clear возникнуть в принципе не может.
Т.е. просто проверять нет ли ошибок после открытия файла )) Думаю оно более универсально? »
Можно. Только не забудьте: а) перед открытием проверить, существует ли этот файл в принципе, дабы не путаться в видах ошибок (коллега megaloman, впрочем, реализовал сию проверку зараз внутри функции); б) вернуть стандартную обработку ошибок (On Error Goto 0) сразу после открытия файла и обработки ошибок.
megaloman, можно и просто:
Это сообщение посчитали полезным следующие участники:
Сообщения: 17 Благодарности: 1
Цитата Iska: Можно. Только не забудьте: а) перед открытием проверить, существует ли этот файл в принципе, дабы не путаться в видах ошибок (коллега megaloman, впрочем, реализовал сию проверку зараз внутри функции); б) вернуть стандартную обработку ошибок (On Error Goto 0) сразу после открытия файла и обработки ошибок. » Спасибо за подсказки!
В общем вот что получилось:
Последний раз редактировалось kosmonavtom, 14-01-2019 в 00:25 . Причина: Код будет выглядеть лушче
Сообщения: 25778 Благодарности: 7508
Проблема только в том, что после всего этого почему то Word не закрывается и висит в диспетчере задач не убитый висит! »
До введения обработки ошибок все нормально было. »
Это сообщение посчитали полезным следующие участники:
Сообщения: 17 Благодарности: 1
Цитата Iska: Это потому, что Вы завершаете исполнение скрипта: до того, как закрываете открытый экземпляр Word’а:» Да! Спасибо. Поменял местами и работает. Очень странно правда, т.к. до этого без обработчика ошибок и так работало!
Еще нужно было подставить ItogoviRezultat в строку 30 примерно:
В итоге вот так записана рабочая версия на практике:
Последний раз редактировалось kosmonavtom, 14-01-2019 в 08:14 . Причина: Добавил обновленный код программы.
Vbs скрипты ошибка
В данной статье я расскажу и покажу, как обрабатывать ошибки в языке VBScript. Расскажу про два оператора объекта Err: On Error Resume Next (Включает обработку ошибок) и On Error GoTo 0 (отключает обработку ошибок). Данные операторы позволяют выполнять определённые выражения после определённых ошибок, а не наблюдать окошко с ошибкой и прерывание выполнения сценария.
Visual Basic Script урезан в своих возможностях по обработке ошибок в отличие от своего большого брата. Осталось только два оператора объекта Err которые мы можем использовать:
On Error Resume Next — Включает обработку ошибок. Если случается ошибка, то она не приводит к прекращению сценария, и мы можем разобраться с ней сами.
On Error GoTo 0 — Отключает обработку ошибок. Стоит по умолчанию.
Свойства объекта Err
Description — Вернёт описание ошибки.
HelpContext — Показывает номер топика открывающейся справки, если пользователь нажмёт F1 в окошке сообщения об ошибке. (Если есть)
HelpFile — Имя файла справки. (Если есть)
Number — Номер ошибки. 0 — отсутствие ошибки.
Source — Возвращает имя приложения, в котором произошла ошибка.
Давайте рассмотрим самый простой пример с обработкой ошибки — деление на 0.
Файла справки для данной ошибки нет и по этому HelpContext вернуло 0, а HelpFile пустую строку. Так же мы увидели, что номер данной ошибки — 11. Теперь давайте обработаем ошибку должным образом.
По сути для деления на 0 хватит и такого выражения:
Но в более сложных сценариях, как брут почтовых сервисов (Yandex.ru, Mail.ru) на VBScript, надо перебрать сначала все возможные ошибки, которые вам известны, а потом на всякий случай застраховаться от неизвестных ошибок.
Особое внимание надо обратить на то, что оператор On Error Resume Next не позволяет обрабатывать синтаксические ошибки.
Методы объекта Err
Clear — данный метод позволяет сбрасывать все свойства и стирать информацию об ошибке. То же самое происходит при использовании операторов: On Error Resume Next, Exit Sub, Exit Function.
Raise — Данный метод позволяет генерировать свою собственную ошибку времени выполнения. Синтаксис: Err.Rise Number [, Source [, Description [, Helpfile [, Helpcontext]]]]
Все параметры — это свойства объекта Err, которые я описал в начале статьи. Обязательный параметр только — номер ошибки. Параметры указываются без скобок!
Теперь что касается оператора On Error GoTo 0. Это редко используемый оператор. Я не рекомендую без крайней необходимости прибегать к нему. Всегда намного надёжней производить обработку ошибок.
На этом у меня всё! Надеюсь, эта статья была для кого то полезной и с подвигла Вас на создание сценариев VBS. До новых встреч на VBHack.Ru!
3 comments
Здравствуйте, к вашему брутеру для яндекс и имеел делал программу, создающую все возможные комбинации из символов. Помогите оптимизировать и убрать бесконечные циклы. Вот код:
Dim value, a, SIMVOL(128) For i = 1 to 128 SIMVOL(i) = chr(i) next ‘All_SIMVOL = join(SIMVOL, «») ‘msgbox All_SIMVOL
Set FSO = CreateObject(«Scripting.FileSystemObject») set Txt = FSO.OpenTextFile(«Pass1.txt», 2, True)
Dim Pass, numb, FSO, Txt
For V1 = 1 to 128 Pass = SIMVOL(V1) Txt.Write(Pass & vbCrlf)
For V1 = 1 to 128 For V2 = 1 to 128 pass = SIMVOL(V1) + SIMVOL(V2) Txt.Write(Pass & vbCrlf) next next
For V1 = 1 to 128 For V2 = 1 to 128 For V3 = 1 to 128 pass = SIMVOL(V1) + SIMVOL(V2) + SIMVOL(V3) Txt.Write(Pass & vbCrlf) next next next
For V1 = 1 to 128 For V2 = 1 to 128 For V3 = 1 to 128 For V4 = 1 to 128 pass = SIMVOL(V1) + SIMVOL(V2) + SIMVOL(V3) + SIMVOL(V4) Txt.Write(Pass & vbCrlf) next next next next
For V1 = 1 to 128 For V2 = 1 to 128 For V3 = 1 to 128 For V4 = 1 to 128 For V5 = 1 to 128 pass = SIMVOL(V1) + SIMVOL(V2) + SIMVOL(V3) + SIMVOL(V4) + SIMVOL(V5) Txt.Write(Pass & vbCrlf) next next next next
Заранее спасибо. (код тут полностью не пишется, скопировать надо и вставить)
Vbs скрипты ошибка
Везде? Если он стоит один раз, то он обработает одну ошибку Это с какого перепугу?
Конструкция On Error Resume Next задает продолжение выполнения с инструкции, непосредственно следующей за инструкцией, которая привела к ошибке выполнения, или с инструкции, непосредственно следующей за вызывающей инструкцией в процедуре, содержащей конструкцию On Error Resume Next. Это позволяет продолжить исполнение программы несмотря на ошибку выполнения. Это позволяет также встроить подпрограмму обработки ошибок в процедуру, а не передавать управление в другую часть процедуры. Конструкция On Error Resume Next становится неактивной при вызове новой процедуры, поэтому для внутренней обработки ошибок необходимо выполнять инструкцию On Error Resume Next в каждой вызываемой процедуре.
Вот фрагмент кода без купюр:
Set ADObject = GetObject(«LDAP://» & dn)
If Err.Number <> 0 Then WScript.Echo «Объект не существует. :(» Else Err.Clear
attrVal = ADObject.Get(«sAMAccountName») If Err.Number = 0 Then WScript.Echo «Логин: » & attrVal
attrVal = ADObject.Get(«telephoneNumber») If Err.Number = 0 Then WScript.Echo «Телефон :» & attrVal
attrVal = ADObject.Get(«otherTelephone») If Err.Number = 0 Then For each a in attrVal WScript.Echo «Телефон :» & a next End if
attrVal = ADObject.Get(«mobile») If Err.Number = 0 Then WScript.Echo «Мобильный :» & attrVal
Скрипт запрашивает атрибуты у объекта АД и выдает их на экран. Если у запрашиваемого объекта АД есть все типы атрибутов, то выдается типа того:
DN: CN=Иванов Иван Иванович, OU=OTDEL, DC=domen, DC=ru Логин: Ivanov-II Телефон: 5-68-97 Телефон: 5-38-12 Телефон: 5-38-13 Мобильный: 8-923-411-23-78
Если у юзера ни одного дополнительного телефона («otherTelephone»), но есть мобильный, то на экране получаем:
DN: CN=Иванов Иван Иванович, OU=OTDEL, DC=domen, DC=ru Логин: Ivanov-II Телефон: 5-68-97
То есть при неуспешном выполнении attrVal = ADObject.Get(«otherTelephone») скрипт просто завершается. И никаких сообщений об ошибке.
Единственный ключ у CScript, имеющий к этому отношение //B — Пакетный режим. Подавляяется отображение ошибок и запросов сценария. На экран вообще ничего не выдается.
attrVal = ADObject.Get(«telephoneNumber») . attrVal = ADObject.Get(«otherTelephone») If Err.Number = 0 Then For each a in attrVal WScript.Echo «Телефон :» & a next End if
ИМХО Когда запрашивается «telephoneNumber», возвращается строка, если телефона нет, то она пустая, но все равно строка. А когда запрашивается «otherTelephone», возвращается массив, ведь «otherTelephone» может быть несколько. А когда в «otherTelephone» нет ни одного телефона, запрос возвращает . х/з что, но не массив, скорее всего какой то NULL. Поэтому к ошибке приводит цикл For, а не ADObject.Get(. ).
Поэтому к ошибке приводит цикл For, а не ADObject.Get(. ). Фиг. Приводит к ошибке как раз ADObject.Get(. ). Выкинул вообще из скрипта attrVal = ADObject.Get(«otherTelephone») If Err.Number = 0 Then For each a in attrVal WScript.Echo «Телефон :» & a next End if
Если у юзера есть «telephoneNumber», то выдается:
DN: CN=Иванов Иван Иванович, OU=OTDEL, DC=domen, DC=ru Логин: Ivanov-II Телефон: 5-68-97 Мобильный: 8-923-411-23-78
Если telephoneNumber» нет, то:
DN: CN=Иванов Иван Иванович, OU=OTDEL, DC=domen, DC=ru Логин: Ivanov-II
Lvm Хм, только щас обратил внимание а Err.Clear после каждого If Err.Number = 0 . кто будет делать?
Значения свойств объекта Err сбрасываются до нулей или пустых строк («») после выполнения инструкций Resume или On Error любого вида, а также после выполнения инструкций Exit Sub, Exit Function или Exit Property в программе обработки ошибки. Для того чтобы непосредственно сбросить значения свойств объекта Err, следует вызвать метод Clear.
Т.е. если ошибка возникла, и ее не сбросить, то она так до конца скрипта и будет тянуться.
С Err.Clear все прекрасно работает, без нее — тот же эффект, что и у тебя. Лично у себя проверял.
Ну, кто бы мог подумать. По обыкновенной, сермяжной логике максимум к чему может привести необнуленный Err.Clear, так это к неправильному выполнению последующего If Err.Number = 0 Then и фсе. А почему объект Err влияет на метод другого объекта — ADObject.Get — для меня загадка. Это типа переполнения буфера ошибок что ли.
hmspns, от меня большой респект и сенкью.
Lvm Да ничего он не влияет и не переполняет. Просто если операция выполнилась без ошибки, с Err ничего не происходит, она не обнуляется и сохраняет то значение, которое было до у нее до удачной операции. Поэтому если одна операция Get дала ошибку, ты Err не очистил, а последующие Get отработали без ошибок, то If Err.Number = 0 Then не пройдет не только после ошибочного оператора, но и после всех последующих.
И что логичней — обнулять Err при правильном выполнении или не обнулять — сложный вопрос.
Может вышеприведенный вариант и работает, но imho, увлечение использованием операторов On Error является само по себе error-ом, тк это может привести к игнорированию других ошибок, что иногда приводит к неожиданным результатам. В Вашем случае сделайте примерно так: