PDA

Показать полную графическую версию : [решено] Как создать лог-файл, если при запуске скрипта произошла ошибка?


V!RTuE
09-02-2015, 16:16
Помогите, пожалуйста. Вот есть скрипт для отправки почты:
strEmail = "mail@mail.ru"
strSMTP = "smtp.mail.ru"
Dim objFSO
Set objFSO = WScript.CreateObject("Scripting.FileSystemObject")
Set objFSO = Nothing
Set objEmail = CreateObject("CDO.Message")
Dim objTextStream, TXT
Set objTextStream = CreateObject("Scripting.FileSystemObject").GetFile("C:\Report.txt").OpenAsTextStream(1)
TXT = objTextStream.ReadAll()
objTextStream.Close
Set objTextStream = Nothing
objEmail.From = "Рога и копыта <mail@mail.ru>"
objEmail.To = "mail@mail.ru"
objEmail.Subject = " 09-02-2015 17:06:51"
objEmail.Textbody = TXT
objEmail.AddAttachment "C:\START.KEY"
objEmail.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
objEmail.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpserver") = strSMTP
objEmail.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25
objEmail.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate") = 1
objEmail.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/sendusername") = "mail@mail.ru"
objEmail.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/sendpassword") = "password"
objEmail.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpusessl") = True
objEmail.Configuration.Fields.Update
objEmail.Send

Как сделать, чтобы при ошибке запуска этого скрипта создавался в этой же папке лог-файл, в который записывалась информация об ошибке?
К примеру, при отсутствии файла, который должен быть прикреплен, выдает ошибку:
Script: C:\sendmail.vbs
Line: 16
Char: 1
Error: The system cannot find the file specified

Code: 80070002
Source: CDO.Message.1
Вот как сделать, чтобы всю эту информацию записать в лог-файл?

Iska
09-02-2015, 18:04
К примеру, при отсутствии файла, который должен быть прикреплен, выдает ошибку: »
А Вы не оставляйте это на волю случая, проверяйте существование файла, который должен быть прикреплён, внутри скрипта.

Вот как сделать, чтобы всю эту информацию записать в лог-файл? »
Запускайте скрипт посредством «cscript.exe», а не «wscript.exe», и перенаправьте вывод потока ошибок в файл.

P.S. Логику:
Dim objFSO
Set objFSO = WScript.CreateObject("Scripting.FileSystemObject")
Set objFSO = Nothing »
не понял ;).

V!RTuE
09-02-2015, 18:34
Запускайте скрипт посредством «cscript.exe», а не «wscript.exe», и перенаправьте вывод потока ошибок в файл. »
а как это правильно делается? Так?

cscript "С:\sendmail.vbs">"C:\my.log"
Если да, то он пишет только это:
Microsoft (R) Windows Script Host Version 5.8
Copyright (C) Microsoft Corporation. All rights reserved.

C:\cons.exe
Если убрать в коде 4 строки (про которые ниже написал), то запишет без C:\cons.exe
P.S. Логику:
Цитата V!RTuE:
Код:
Dim objFSO
Set objFSO = WScript.CreateObject("Scripting.FileSystemObject")
Set objFSO = Nothing
»
не понял . »

я неправильно скопировал)) Вот что там у меня. Хотя я уже сам не помню зачем оно надо. Без этих строк тоже всё работает)))
echo Dim objFSO
echo Set objFSO = WScript.CreateObject("Scripting.FileSystemObject")
echo WScript.Echo objFSO.BuildPath(objFSO.GetParentFolderName(WScript.ScriptFullName), "cons.exe")
echo Set objFSO = Nothing

Iska
09-02-2015, 18:57
а как это правильно делается? Так? »
Нет. Так Вы перенаправляете только стандартный поток вывода («stdout»), а надо — поток ошибок («stderr»):
cscript.exe "С:\sendmail.vbs" 2>"C:\my.log"
тогда поток вывода пойдёт по-прежнему на консоль, а поток ошибок будет перенаправлен в файл.

V!RTuE
09-02-2015, 19:19
А Вы не оставляйте это на волю случая, проверяйте существование файла, который должен быть прикреплён, внутри скрипта. »
у меня основной код в батнике. И там проверка уже реализована на наличие файлов. Вот пример:
SET f=%~dp0
if exist "%f%START.KEY" echo objEmail.AddAttachment "%f%START.KEY">>"%f%ARCHIVE\sendmail.vbs"
Просто отправка почты у меня реализована созданием и запуском скрипта из батника :)
А вообще я не удачный пример привел на счет отсутствия файла. Основная причина, по которой мне надо вести лог ошибки, это когда вообще скрипт не может отработать нормально. Вот например такая ошибка на некоторых компьютерах возникает:
http://f5.s.qip.ru/Kzjldbc1.jpg
И пока не знаю как она решается ((

Iska
09-02-2015, 20:01
у меня основной код в батнике. И там проверка уже реализована на наличие файлов. Вот пример: »
Я бы предпочёл делать сие непосредственно в скрипте. И вообще целиком перейти на WSH (или PoSH) с пакетных файлов, нежели пользовать подобную «солянку».

И пока не знаю как она решается (( »
Например, так:
Option Explicit

Dim objMessage


On Error Resume Next
Set objMessage = WScript.CreateObject("CDO.Message")

If Err.Number = 0 Then
On Error Goto 0

'…
'…
'…

Set objMessage = Nothing
Else
Err.Clear
On Error Goto 0

WScript.Echo "Can't create object [CDO.Message]"
WScript.Quit 1
End If

WScript.Quit 0

К сожалению, в VBScript нет удобного механизма «try… catch… finally», наличествующего в JScript.

P.S. При использовании механизма перенаправления потока ошибок, описанного выше, стоит писать именно туда, т.е., не:
WScript.Echo "Can't create object [CDO.Message]"
а:
WScript.StdErr.WriteLine "Can't create object [CDO.Message]"

V!RTuE
09-02-2015, 22:12
Я бы предпочёл делать сие непосредственно в скрипте. И вообще целиком перейти на WSH (или PoSH) с пакетных файлов, нежели пользовать подобную «солянку». »
Может так и лучше будет, но я не программист (юрист по образованию). Для меня и батники не так легко даются. Ну а во-вторых уж слишком много действий выполняет батник (почти 800 строк кода). А в-третьих, надо сделать универсальным, чтобы работало на любой ОС (от Win 2000 до серверных). Если интересно, и можете подсказать как лучше реализовать, то полную версию батника могу выслать в лс.

Например, так:
Option Explicit

Dim objMessage


On Error Resume Next
Set objMessage = WScript.CreateObject("CDO.Message")

If Err.Number = 0 Then
On Error Goto 0

'…
'…
'…

Set objMessage = Nothing
Else
Err.Clear
On Error Goto 0

WScript.Echo "Can't create object [CDO.Message]"
WScript.Quit 1
End If

WScript.Quit 0

а тут вообще не понял куда свой код вставлять (( Знаний по VBS практически нет у меня

Iska
10-02-2015, 02:22
А в-третьих, надо сделать универсальным, чтобы работало на любой ОС (от Win 2000 до серверных). »
Тогда только WSH. И всё равно — набор классов Wbem и их свойств и методов различен для разных ОС.

то полную версию батника могу выслать в лс. »
Не стоит.

а тут вообще не понял куда свой код вставлять (( Знаний по VBS практически нет у меня »
Надо учиться. Ваш код должен находиться там, где закомментированные многоточия. Но просто «взять и вставить» не получится.

V!RTuE
10-02-2015, 07:39
cscript.exe "С:\sendmail.vbs" 2>"C:\my.log" »
Возник еще один вопрос. В лог пишется такая информация:
C:\sendmail.vbs(16, 1) CDO.Message.1: The system cannot find the file specified.
а возможно чтобы еще и записывало "Code: 80070002"? Он ведь есть во всплывающем окне.

Iska
10-02-2015, 09:42
а возможно чтобы еще и записывало "Code: 80070002"? Он ведь есть во всплывающем окне. »
Нет. Только по вышеописанной методике (http://forum.oszone.net/post-2469167.html#post2469167) самому обрабатывать ошибки и писать в stderr любое содержимое из объекта «Err».

Ещё раз повторю: сделайте проверку существования файла в самом скрипте. Это будет проще.

V!RTuE
13-02-2015, 02:27
Нет. Только по вышеописанной методике самому обрабатывать ошибки и писать в stderr любое содержимое из объекта «Err». »
Ну в общем мой окончательный вариант получился такой:
on error resume next
Dim objFS, objEmail, objLog
Dim strEmail, strSMTP, strLog
Dim objTextStream, TXT, s
Set objFS = CreateObject("Scripting.FileSystemObject")
Set objEmail = CreateObject("CDO.Message")
strEmail = "mail@mail.ru"
strSMTP = "smtp.mail.ru"
strLog = "H:\ARCHIVE\Sendmail_log.txt"
Set objTextStream = objFS.GetFile("H:\ARCHIVE\Report.txt").OpenAsTextStream(1)
TXT = objTextStream.ReadAll()
objTextStream.Close
Set objTextStream = Nothing
if (objFS.FileExists(strLog)) then
set objLog = objFS.OpenTextFile(strLog, 8, False)
else
Set objLog = objFS.CreateTextFile(strLog, False)
end if
objEmail.From = "Рога и копыта <mail@mail.ru>"
objEmail.To = "mail@mail.ru"
objEmail.Subject = " 13-02-2015 02:42:32"
objEmail.Textbody = TXT
objEmail.AddAttachment "H:\START.KEY"
if Err.Number <> 0 then
s = ""
s = "Err.Number: " & Hex(Err.Number) & vbCrLf & _
"Source: " & Err.Source & vbCrLf & _
"Reason: " & Err.Description
objLog.Write(s)
end if
objEmail.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
objEmail.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpserver") = strSMTP
objEmail.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25
objEmail.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate") = 1
objEmail.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/sendusername") = "mail@mail.ru"
objEmail.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/sendpassword") = "password"
objEmail.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpusessl") = True
objEmail.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpconnectiontimeout") = 60
objEmail.Configuration.Fields.Update
objEmail.Send
if Err.number <> 0 then
s = ""
s = "Err.Number: " & Hex(Err.Number) & vbCrLf & _
"Source: " & Err.Source & vbCrLf & _
"Reason: " & Err.Description
objLog.Write(s)
end if
objLog.Close
Set objLog = Nothing
Set objFS = Nothing
В принципе информации должно хватить, чтобы проанализировать логи. Ну а вообще есть мысли объединить этот вариант и этот (чтобы знать в какой строчке ошибка):
cscript "H:\ARCHIVE\Sendmail.vbs" 2>"H:\ARCHIVE\Sendmail_log2.txt""
У меня всё-равно через батник запускается. Но тогда придется 2 раза запускать скрипт отправки почты (для второго раза переделать код, убрав из него всё, что касается записи в лог ошибок). Ну и получится, что в случае отсутствия ошибок, почта отправится дважды. :)
Ещё раз повторю: сделайте проверку существования файла в самом скрипте. Это будет проще.
Я тоже повторюсь: эту причину я указал в качестве примера. Проверка уже реализована в батнике (скрипт вообще из самого батника создается в процессе работы). А так основная причина для ведения логов это если вообще блокируется отправка почты (антивирус, фаервол, отсутствие инета) или каких то компонентов не хватает для работы самого скрипта.

Iska
13-02-2015, 02:35
Ну в общем мой окончательный вариант получился такой:
on error resume next
… »
Это самый верный и надёжный способ не только вообще не увидеть ошибок, но и не узнать о том, что они были.

«On Error Resume Next» должно находиться перед командой, которая может вызвать ошибку, а не в начале скрипта. Обработка ошибки должна происходить сразу же после команды, которая может вызвать ошибку, и сразу же следом — включение стандартной процедуры обработки ошибок («On Error Goto 0»).




© OSzone.net 2001-2012