Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Скриптовые языки администрирования Windows (http://forum.oszone.net/forumdisplay.php?f=102)
-   -   [решено] Как создать лог-файл, если при запуске скрипта произошла ошибка? (http://forum.oszone.net/showthread.php?t=295250)

V!RTuE 09-02-2015 16:16 2468993

Как создать лог-файл, если при запуске скрипта произошла ошибка?
 
Помогите, пожалуйста. Вот есть скрипт для отправки почты:
Код:

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 2469083

Цитата:

Цитата V!RTuE
К примеру, при отсутствии файла, который должен быть прикреплен, выдает ошибку: »

А Вы не оставляйте это на волю случая, проверяйте существование файла, который должен быть прикреплён, внутри скрипта.

Цитата:

Цитата V!RTuE
Вот как сделать, чтобы всю эту информацию записать в лог-файл? »

Запускайте скрипт посредством «cscript.exe», а не «wscript.exe», и перенаправьте вывод потока ошибок в файл.

P.S. Логику:
Цитата:

Цитата V!RTuE
Код:

Dim objFSO
Set objFSO = WScript.CreateObject("Scripting.FileSystemObject")
Set objFSO = Nothing

»

не понял ;).

V!RTuE 09-02-2015 18:34 2469113

Цитата:

Цитата Iska
Запускайте скрипт посредством «cscript.exe», а не «wscript.exe», и перенаправьте вывод потока ошибок в файл. »

а как это правильно делается? Так?

Код:

cscript "С:\sendmail.vbs">"C:\my.log"
Если да, то он пишет только это:
HTML код:

Microsoft (R) Windows Script Host Version 5.8
Copyright (C) Microsoft Corporation. All rights reserved.

C:\cons.exe

Если убрать в коде 4 строки (про которые ниже написал), то запишет без C:\cons.exe
Цитата:

Цитата Iska
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 2469132

Цитата:

Цитата V!RTuE
а как это правильно делается? Так? »

Нет. Так Вы перенаправляете только стандартный поток вывода («stdout»), а надо — поток ошибок («stderr»):
Код:

cscript.exe "С:\sendmail.vbs" 2>"C:\my.log"
тогда поток вывода пойдёт по-прежнему на консоль, а поток ошибок будет перенаправлен в файл.

V!RTuE 09-02-2015 19:19 2469152

Цитата:

Цитата Iska
А Вы не оставляйте это на волю случая, проверяйте существование файла, который должен быть прикреплён, внутри скрипта. »

у меня основной код в батнике. И там проверка уже реализована на наличие файлов. Вот пример:
Код:

SET f=%~dp0
if exist "%f%START.KEY" echo objEmail.AddAttachment "%f%START.KEY">>"%f%ARCHIVE\sendmail.vbs"

Просто отправка почты у меня реализована созданием и запуском скрипта из батника :)
А вообще я не удачный пример привел на счет отсутствия файла. Основная причина, по которой мне надо вести лог ошибки, это когда вообще скрипт не может отработать нормально. Вот например такая ошибка на некоторых компьютерах возникает:
Скрытый текст

И пока не знаю как она решается ((

Iska 09-02-2015 20:01 2469167

Цитата:

Цитата V!RTuE
у меня основной код в батнике. И там проверка уже реализована на наличие файлов. Вот пример: »

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

Цитата:

Цитата V!RTuE
И пока не знаю как она решается (( »

Например, так:
Код:

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 2469236

Цитата:

Цитата Iska
Я бы предпочёл делать сие непосредственно в скрипте. И вообще целиком перейти на 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 2469313

Цитата:

Цитата V!RTuE
А в-третьих, надо сделать универсальным, чтобы работало на любой ОС (от Win 2000 до серверных). »

Тогда только WSH. И всё равно — набор классов Wbem и их свойств и методов различен для разных ОС.

Цитата:

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

Не стоит.

Цитата:

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

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

V!RTuE 10-02-2015 07:39 2469334

Цитата:

Цитата Iska
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 2469365

Цитата:

Цитата V!RTuE
а возможно чтобы еще и записывало "Code: 80070002"? Он ведь есть во всплывающем окне. »

Нет. Только по вышеописанной методике самому обрабатывать ошибки и писать в stderr любое содержимое из объекта «Err».

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

V!RTuE 13-02-2015 02:27 2470714

Цитата:

Цитата Iska
Нет. Только по вышеописанной методике самому обрабатывать ошибки и писать в 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 2470717

Цитата:

Цитата V!RTuE
Ну в общем мой окончательный вариант получился такой:
Код:

on error resume next

»

Это самый верный и надёжный способ не только вообще не увидеть ошибок, но и не узнать о том, что они были.

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


Время: 04:55.

Время: 04:55.
© OSzone.net 2001-