VBScript collect events print from Windows logs

Скрипт позволяет собирать события печати из журналов Windows с локального или удаленного компьютера(ов) и импортировать их в базу Oracle.

Требования для машины, на которой запускаете скрипт:

  • ОС Windows  (7, XP, Server 2003, Server 2008)
  • Oracle client (or instant client) version 10.2 and above.
  • Запускать скрипт под пользователем, который входит в группу Администрирования на других компьютерах сети.

Требования к базе Oracle:

  • Oracle DB 10.2 and above.
  • Создать в какой-нибудь схеме базы Oracle таблицы:
/* список компьютеров, по которым нужно собирать события печати */
CREATE TABLE PRINTLOG_COMPUTERS
(COMPUTER       VARCHAR2(100));
/* сюда будут писаться данные по печати */
CREATE TABLE PRINTLOG
(SYSDATETIME    DATE,
CREATEDTIME     DATE,
OS              VARCHAR2(50),
EVENTID         NUMBER,
SOURCENAME      VARCHAR2(128),
COMPUTER        VARCHAR2(100),
USERNAME        VARCHAR2(128),
MESSAGE         VARCHAR2(4000));
/* сюда будут писаться ошибки, возникающие при сборе событий */
CREATE TABLE PRINTLOG_ERROR
(SYSDATETIME    DATE,
COMPUTER        VARCHAR2(100),
ERRORMESSAGE    VARCHAR2(512));
  • В таблицу PRINTLOG_COMPUTERS внести имена компьютеров, по которым будет собираться статистика печати.

Требования к компьютерам, с которых будут собираться события печати из журналов Windows:

  • Желательно, чтобы компьютеры были под управлением Windows (7, XP, Server 2003, Server 2008)
  • И чтобы находились в одном домене

Исходник скрипта, с комментариями:

'### [ VBScript ]
'### (c) 02.04.2015
'### What: collects events printing (10, 307) from Windows events logs on local or remote computer and writes them to the Oracle database
'### Author: souluran

Dim objWMIService
Dim colLoggedEvents
Dim colLogFiles
Dim ObjLogFile
Dim objEvent
Dim errCon
Dim errMessage
Dim strSearchString
Dim con
Dim objRecordset
Dim PROC, SQL, ERRINS, INS
Dim objRegistry
Dim strKeyPath
Dim flag
Dim arrSubKeys
Dim subkey
Dim EventCode
Dim LogFile
Dim OverWrite
Const HKEY_LOCAL_MACHINE = &H80000002

On Error Resume Next

'--> connection parameters to Oracle
Driver   = "************" '--> for example "Oracle in instantclient_11_2"
dbName   = "************"
dbUser   = "************" '--> better to have a user with the DBA or have privileges Select/Insert/Delete on tables PRINTLOG_COMPUTERS, PRINTLOG, PRINTLOG_ERROR
Password = "************"
dbSchema = "************" '--> scheme that created the table PRINTLOG_COMPUTERS, PRINTLOG, PRINTLOG_ERROR

'--> open connect to Oracle
Set con = CreateObject("ADODB.Connection")
con.ConnectionTimeOut = 20
con.CommandTimeout = 120
con.Open "Driver={" & Driver & "};DBQ=" & dbName & ";UID=" & dbUser & ";PWD=" & Password

Err.Clear
'--> check connect to Oracle
If Err.Number <> 0 Then
    'error handling:
    errCon = "ORACLE: " & Err.Number & " Srce: " & Err.Source & " Desc: " &  Err.Description
    'WScript.Echo errStr
    Err.Clear
    'WScript.Quit
End If

'--> set the start and the end dates for the collection
begdate = "20150101 00:00:00"
enddate = "20150430 23:59:59"

'--> get list of computers
SQL = "select COMPUTER from " & dbSchema & ".PRINTLOG_COMPUTERS order by 1"
Set objRecordset = con.Execute(SQL)
Do Until objRecordset.EOF
    
    Computer = objRecordset.Fields("COMPUTER").Value
    'WScript.Echo Computer

Err.Clear
    '--> check computer to access
    Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & Computer & "\root\cimv2")
    If Err.Number <> 0 Then
        errMessage = Err.Description
        'WScript.Echo errMessage
        ERRINS = "INSERT INTO " & dbSchema & ".printlog_error VALUES(sysdate,'" & Computer & "','" & errMessage & "')"
        Set objRecordsetErr = con.Execute(ERRINS)
        Err.Clear
        errMessage = vbNullString
    Else    
        '--> check version OS Windows
        Set colOperatingSystems = objWMIService.ExecQuery("Select * from Win32_OperatingSystem")
        OS = vbNullString
        For Each objOperatingSystem in colOperatingSystems
            OS = objOperatingSystem.Caption
            Exit For
        Next
        'WScript.Echo OS
        
        '--> set logfile and evencode for Windows XP and 7
        If InStr(OS, "Windows XP") > 0 Or InStr(OS, "Windows(R) XP") > 0 Or
  InStr(OS, "Server 2003") > 0 Then
            LogFile = "System"
            EventCode = "10" 'event print for Windows XP (2003)
        ElseIf InStr(OS, "Windows 7") > 0 Or InStr(OS, "Windows(R) 7") Or InStr(OS, "Server 2008") > 0 Then
            LogFile = "Microsoft-Windows-PrintService/Operational"
            EventCode = "307" 'event print for Windows 7 (2008)
            
            '--> check exists registry key for read printing events on Windows 7
            Set objRegistry = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & Computer & "\root\default:StdRegProv")
            strKeyPath = "SYSTEM\CurrentControlSet\services\eventlog"
            objRegistry.EnumKey HKEY_LOCAL_MACHINE, strKeyPath, arrSubKeys
            flag = 0
            For Each subkey In arrSubKeys
                If subkey = LogFile Then
                    flag = 1
                    Exit For
                End If
            Next
            
            If flag = 0 Then
                'WScript.Echo "Create new key Microsoft-Windows-PrintService/Operational."
                strKeyPath = "SYSTEM\CurrentControlSet\services\eventlog\Microsoft-Windows-PrintService/Operational"
                objRegistry.CreateKey HKEY_LOCAL_MACHINE, strKeyPath
            End If
        End If
    
        Rec = 0
        '--> check the log for events
        Set colLogFiles = objWMIService.ExecQuery("Select * from Win32_NTLogEvent Where Logfile = '" & LogFile & "' and EventCode = '" & EventCode & "'")
        For Each ObjLogFile In colLogFiles
            Rec = 1
            Exit For
        Next
    
        If Rec = 0 Then
            errMessage = "The " & LogFile & " are failed or not contained events " & EventCode
            'WScript.Echo errMessage
            ERRINS = "INSERT INTO " & dbSchema & ".PRINTLOG_ERROR VALUES(sysdate,'" & Computer & "','" & errMessage & "')"
            Set objRecordsetErr = con.Execute(ERRINS)
            errMessage = vbNullString
        Else 
        
        '--> option overwrite exists records in table (0 - OFF, 1 - ON)
        OverWrite = 0
        If OverWrite = 1 Then
            DEL = "DELETE FROM " & dbSchema & ".PRINTLOG where computer = '" & computer & "' and trunc(CREATEDTIME) >= to_date(substr('" & begdate & "', 1, 8), 'yyyymmdd') " _
                & " and trunc(CREATEDTIME) <= to_date(substr('" & enddate & "', 1, 8), 'yyyymmdd')"
            Set objRecordsetDel = con.Execute(DEL)
        End If

            '--> search events in a given period
            cnt = 0        
            Set colLoggedEvents = objWMIService.ExecQuery("Select * from Win32_NTLogEvent Where Logfile = '" & LogFile & "' and EventCode = '" & EventCode & "' and TimeGenerated >= '"& begdate &"' and TimeGenerated <= '" & enddate & "'")
            cnt = colLoggedEvents.Count
            If cnt > 0 Then
                'WScript.Echo cnt
                For Each objEvent In colLoggedEvents
                     strSearchString = objEvent.Message
                 
                     EventCode = objEvent.EventCode
                     SourceName = objEvent.SourceName
                     If InStr(objEvent.ComputerName, ".keramin.int") > 0 Then
                        ComputerName = LCase(objEvent.ComputerName)
                     Else
                        ComputerName = LCase(objEvent.ComputerName) & ".keramin.int"
                     End If
                     UserName = LCase(objEvent.User)
                     CreatedTime = objEvent.TimeWritten
                     Message = Replace(objEvent.Message, "'", "")
                         
                     INS = "INSERT INTO " & dbSchema & ".PRINTLOG VALUES(sysdate, to_date(substr('" & CreatedTime & "', 1, 14), 'yyyymmddhh24miss'),'" & OS & "','" & EventCode & "','"    & SourceName & "','" & ComputerName & "','" & UserName & "','" & Message & "')"
                     Set objRecordsetIns = con.Execute(INS)
                             
                Next

            Else
                errMessage = "There was no events print in " & LogFile & " from " & begdate & " to " & enddate
                'WScript.Echo errMessage
                'ERRINS = "INSERT INTO " & dbSchema & ".PRINTLOG_ERROR VALUES(sysdate,to_date(substr('" & begdate & "', 1, 8), 'yyyymmdd'),'" & Computer & "','" & errMessage & "')"
                'Set objRecordsetErr = con.Execute(ERRINS)
                errMessage = vbNullString
            End If
        End if
    End If
    
objRecordset.MoveNext
Loop

'--> close connect to Oracle
con.Close
Set objRecordsetErr = Nothing
Set objRecordsetIns = Nothing
Set objRecordsetDel = Nothing
Set con = Nothing
 >        End if
    End If
    
objRecordset.MoveNext
Loop

'--> close connect to Oracle
con.Close
Set objRecordsetErr = Nothing

А вот маленький запрос =), который возвращает нужные для статистики данные по таблице PRINTLOG:

SELECT SYSDATETIME,
         CREATEDTIME,
         EVENTID,
         SOURCENAME,
         COMPUTER,
         OS,
         USERNAME,
         SUBSTR (
            REGEXP_REPLACE (MESSAGE,
                            'Документ \d+, |Document \d+, ',
                            ''),
            1,
              REGEXP_INSTR (
                 REGEXP_REPLACE (MESSAGE,
                                 'Документ \d+, |Document \d+, ',
                                 ''),
                 'владельца|owned|, которым владеет')
            - 1)
            DOC,
         REGEXP_REPLACE (
            TRIM (
               REGEXP_REPLACE (
                  SUBSTR (
                     MESSAGE,
                     REGEXP_INSTR (
                        MESSAGE,
                        'владельца|owned by|, которым владеет')),
                  'владельца |owned by |, которым владеет')),
            ' (.*)')
            OWNER,
         SUBSTR (
            REGEXP_REPLACE (
               SUBSTR (
                  MESSAGE,
                  REGEXP_INSTR (
                     MESSAGE,
                     'напечатан на |был распечатан на |was printed ')),
               'напечатан на |был распечатан на |was printed on '),
            1,
              REGEXP_INSTR (
                 REGEXP_REPLACE (
                    SUBSTR (
                       MESSAGE,
                       REGEXP_INSTR (
                          MESSAGE,
                          'напечатан на |был распечатан на |was printed on ')),
                    'напечатан на |был распечатан на |was printed on '),
                 'через порт|via port|through port')
            - 2)
            PRINTER,
         SUBSTR (
            REGEXP_REPLACE (
               SUBSTR (
                  MESSAGE,
                  REGEXP_INSTR (MESSAGE,
                                'через порт |via port |through port ')),
               'через порт |via port |through port '),
            1,
              REGEXP_INSTR (
                 REGEXP_REPLACE (
                    SUBSTR (
                       MESSAGE,
                       REGEXP_INSTR (
                          MESSAGE,
                          'через порт |via port |through port ')),
                    'через порт |via port |through port '),
                 ' Размер: | Размер в байтах: | Size in bytes: ')
            - 3)
            PORT,
         SUBSTR (
            REGEXP_REPLACE (
               SUBSTR (
                  MESSAGE,
                  REGEXP_INSTR (
                     MESSAGE,
                     'Размер: |Размер в байтах: |Size in bytes: ')),
               'Размер: |Размер в байтах: |Size in bytes: '),
            1,
              REGEXP_INSTR (
                 REGEXP_REPLACE (
                    SUBSTR (
                       MESSAGE,
                       REGEXP_INSTR (
                          MESSAGE,
                          'Размер: | Размер в байтах: | Size in bytes: ')),
                    'Размер: | Размер в байтах: | Size in bytes: '),
                 ' байт;|число страниц: |(.|;) Pages printed: |(.|;) Страниц напечатано: ')
            - 1)
            BYTES,
         TRIM (
            REGEXP_REPLACE (
               SUBSTR (
                  MESSAGE,
                  REGEXP_INSTR (
                     MESSAGE,
                     ' байт; |число страниц: | Pages printed: | Страниц напечатано: ')),
                  ' байт; |число страниц: |Страниц напечатано: |(p|P)ages printed: |[.] Действий пользователя не требуется[.]|[.] No user action is required[.]|'
               || CHR (13)
               || CHR (10)))
            PAGES,
         MESSAGE
FROM printlog
ORDER BY 1;

Если будут какие-то вопросы обращайтесь, возможно помогу.
Также в скором времени создам пост с подобный скриптом, но написанном на Python.

Реклама

Write the result of SQL-query in file with encoding UTF-8 without BOM

Скрипт позволяет выгрузить результат SQL-запроса (MS SQL Server) в текстовый файл с разделителями в кодировке UTF-8 без BOM.

Dim oSource
Dim oDatabase
Dim oUser
Dim oPassword
Dim conn
Dim cmd
Dim rs
Dim fs
Dim arr
Dim textStream
Dim FileName
Dim strLine, Str
Dim Res
Dim sep
Dim i
Dim dblQuate

'Enter settings for connecting to MS SQL database
oSource = "mssqlsrv"
oDatabase = "hwiproducts"
oUser = "hwiuser"
oPassword = "*******"

Set conn = CreateObject("ADODB.Connection")
conn.Open "Provider=SQLOLEDB;Data Source=" _
    & oSource & ";Trusted_Connection=Yes;Initial Catalog=" _
    & oDatabase & ";User ID=" & oUser & ";Password=" & oPassword & ""

Set cmd = CreateObject("ADODB.Command")
Set cmd.ActiveConnection = conn

'Place your SQL-Query
cmd.CommandText = "SELECT TYPENAME, " _
                 & "MDNAME, " _
                 & "SN, " _
                 & "STRIHCODE, " _
                 & "VENDOR, " _
                 & "convert(varchar(20), INDEMNITYD, 120) INDEMNITYD, " _
                 & "convert(varchar(20),GUARANT,120) GUARANT, " _
                 & "DEP " _
                 & "FROM [hwiproducts].[dbo].[productstores]" _
                 & "WHERE TYPEEQU = 'Printers'"

'Execute your SQL-Query
Set rs = cmd.Execute
 
'Specify the full path to the file to which we write the query result
FileName = "d:\PLANTRACE\HWI\Printers.csv"
 
Set fs = CreateObject("Scripting.FileSystemObject")

'Check the existence of the file and delete it (if necessary)
If fs.FileExists(FileName) Then
   fs.DeleteFile(FileName)
End If

Set textStream = fs.OpenTextFile(FileName, 8, True)

'Specifies the separator
sep = ","

Do Until rs.EOF
    
    'Count the number of fields
    ColCount = rs.Fields.Count - 1
    
    For i = 0 To ColCount
        'Add double quotes to values (if necessary)
        dblQuate = """"& rs(rs.Fields(i).Name) &""""
        
        'Form a string to write to the file
        strLine = strLine & sep & dblQuate
        
        If i = ColCount Then
            
            'Separator to remove from the beginning of the string
            Str = Replace(strLine,",","",1,1)
            
            'Convert string to UTF-8 without BOM and write it in file
            Res = StrConvert (Str, "Windows-1251", "UTF-8")
            textStream.WriteLine Res
            
            'When a string is writed then clean it
            strLine = ""
        End If
    Next
    
    'Next row from result query
    rs.MoveNext
Loop

'Close stream, command and connecting
textStream.Close
rs.Close
conn.Close

Function StrConvert(Text, FromCharset, ToCharset)
'What's: converts the string in encoding UTF8 without BOM
Dim Stream

Set Stream = CreateObject("ADODB.Stream")
    Stream.Type = 2
    Stream.Mode = 3
    Stream.Open
    Stream.Charset = ToCharset
    Stream.WriteText Text
    Stream.Position = 0
    Stream.Charset = FromCharset
    BOM = Stream.ReadText(3)

'Skip BOM bytes
If AscB(MidB(BOM, 1, 1)) = 239 And AscB(MidB(BOM, 2, 1)) = 187 _
                             And AscB(MidB(BOM, 3, 1)) = 191 Then
    Stream.Position = 3
 Set fOut = CreateObject("adodb.stream")
    fOut.Type = 2
    fOut.Mode = 3
    fOut.Open
    fOUT.WriteText Text
    StrConvert = fOUT.ReadText
Else
    StrConvert = Stream.ReadText
End If
 
End Function

Start the process when it is not running (by vbscript)

Иногда требуется проверить запущен ли процесс (например, notepad.exe) под пользователем (user1), чтобы случайно не запустить его дважды, или вообще запустить его, если он отсутствует в списке процессов. Я описал пример запуска java.exe для компиляции apex.war (запуска Oracle Apex listener 2.0.3), при условии, что база данных APEX (Oracle) работает и процесс не запущен. Для проверки запущен ли процесс, написал функцию SearchProcess, которая возвращает 1, если процесс запущен.

'(с) 19.05.2014
Dim ObjShell, Shell
Dim ObjProc
Dim StrORA
Dim dblist
Dim chekdir
Dim procname
Dim ownername
Dim Res
Dim JavaHome

'Указываем путь к java.exe нужно нам версии
JavaHome="c:\Program Files\Java\jdk1.6.0_18\bin\java.exe"

'Подключение к базе (Oracle)
Set ObjShell = CreateObject("WScript.Shell")
WScript.Sleep 600
StrORA = "sqlplus /@APEX as sysdba @x:\apexlistener\connect.sql" 'файл connect.sql содержит следующий код: select sysdate from dual; exit
Set ObjProc = ObjShell.Exec(StrORA)

input = ""
strOutput = ""
'Читаем output нашего соединения к базе
Do While Not ObjProc.StdOut.AtEndOfStream
input = input &amp; vbCrLf &amp; ObjProc.StdOut.ReadLine
Loop

'Если соединение завершилось успешно
If InStr(input, "SYSDATE") Then
'Проверяем запущен ли процесс под этим владельцем
Res = SearchProcess("java.exe", "orauser")
If Res 1 Then
StrORA = JavaHome &amp; " -Dapex.home=x:\apex\8090 -Dapex.port=8090 -Dapex.images=x:\apex\images -jar apex.war"
Set ObjProc = ObjShell.Exec(StrORA)
End IF
Else
'WScript.Echo "ORACLE is DISABLE!"
End If

Function SearchProcess(procname, ownername)
'(c) 19.05.2014
'What's: проверяет запущен ли процесс на компьютере и кто его владелец
' procname - имя процесса
' ownername - имя пользователя, под кем запущен процесс

Dim strComputer ' Имя компьютера
Dim objService ' Объект SWbemServices
Dim colProcesses ' Коллекция экземпляров класса WMI
Dim objProcess ' Элемент коллекции
Dim WshShell ' Объект WshShell
Dim cnt 'счетчик
Dim Return
Dim strNameOfUser

Set WshShell = WScript.CreateObject("WScript.Shell")

' "." - локальный компьютер
strComputer = "."

' Подключаемся к пространству имен WMI
Set colProcesses = GetObject("winmgmts:" &amp; "{impersonationLevel=impersonate}!\\" &amp; strComputer &amp; "\root\cimv2").ExecQuery("SELECT * FROM Win32_Process")

if colProcesses.Count &gt; 0 Then

'Перебираем коллекцию
For Each objProcess in colProcesses

'Проверяем искомый процесс
If objProcess.Name = procname Then
' Проверяем владельца процесса
Return = objProcess.GetOwner(strNameOfUser)
If Return = 0 Then
If strNameOfUser = ownername Then
SearchProcess = 1
'WScript.Echo "Process " &amp; objProcess.Name &amp; " is owned by " &amp; "\" &amp; strNameOfUser &amp; "."
End If
End If
End If
Next
End If

End Function