Отчёт о запуске программ на компьютерах пользователей

от автора

Всем привет!
Отчёт о том, что запускает пользователь на своём компьютере, крайне важен. С многих точек зрения. Особенно с точки зрения информационной безопасности.
Информация о запуске программ на компьютерах пользователей храниться в журнале безопасности. Конечно, рассматривается среда Windows. В Инете готового решения не нашёл, поэтому сделал свою реализацию.
Скрипт запускается на сервере. На выходе имеем набор файлов с отчётами о запуске программ.
Картинка для привлечения внимания:


Основная идея такая. Текущие события журнала безопасности сохраняются в evt-файле на клиентском компьютере. Файл копируется на сервер, где информация из него загружается на SQL Server. Затем SQL-запросом формируется отчёт и сохраняется в файл.
Теперь, как это реализовано.
Необходимо создать папки Log, Logs, CheckComps, Logi_ForReports и Computer. У меня папки на диске F. В папке Log создать файл list.txt со списком компьютеров, которые необходимо проверить. Каждое имя компьютера с новой строки. Я создал 2 файла list.txt и list7.txt для XP и семёрок соответственно. В папке Computer создать файл is_computer_online_listComps.vbs

Содержимое файла is_computer_online_listComps.vbs:

on error resume next  dim gsFileName dim gsRunCmd dim gix dim giy dim giz  if Wscript.Arguments.Count = 1 then 	gsFileName = Wscript.Arguments(0) 	gsOS = "XP" elseif Wscript.Arguments.Count = 2 then 	gsFileName = Wscript.Arguments(0) 	gsOS = Wscript.Arguments(1) else 	gsFileName = InputBox("Файл со списком компьютеров", "Ввод", "F:\Log\list.txt") 	gsOS = InputBox("Тип операционной системы:" & VBNewLine & "'XP' - для Windows 2000/XP" & VBNewLine & "'7' - для Windows 7", "Ввод", "XP") end if  gsOS = uCase(gsOS) wscript.echo "gsOS: " & gsOS if inStr(gsOS, "XP") = 0 and inStr(gsOS, "7") = 0 then 	MsgBox "Некорректно указан тип операционной системы!", vbInformation, "Внимание" 	Wscript.Quit end if  WScript.Echo "Файл со списком компьютеров: " & gsFileName  Set objFSO = CreateObject("Scripting.FileSystemObject") Set objTextFileOpen = objFSO.OpenTextFile(gsFileName, 1)  gix = 0 giy = 0  Set WshShell = CreateObject("WScript.Shell")  do until objTextFileOpen.AtEndOfStream 	gsComputerName = objTextFileOpen.Readline 	giy = giy + 1 loop   objTextFileOpen.Close  wscript.echo "Найдено компьютеров: " & giy  Set objTextFileOpen = objFSO.OpenTextFile(gsFileName, 1)  do until objTextFileOpen.AtEndOfStream 	gsComputerName = objTextFileOpen.Readline 	gix = gix + 1 	giz = gix * 100 	giz = giz / giy 	giz = Round(giz, 1) 	giOst = giy - gix 	 	if fuPing(gsComputerName) then 		wscript.echo gsComputerName & VBTab & " осталось: " & giOst & ", готово: " & giz & "%" 		 		if inStr(gsOS, "XP") then 			gsRunCmd = "f:\Computer\is_computer_online.bat " & gsComputerName & " y" 		elseif inStr(gsOS, "7") then 			gsRunCmd = "f:\Computer\is_computer_online7.bat " & gsComputerName & " y" 		end if 		WshShell.Run gsRunCmd 		if giOst <> 0 then 			WScript.Sleep 180000 ' Внимание! Вот это задержка в 180 секунд между компьютерами. 		end if 	else 		wscript.echo gsComputerName & VBTab & " осталось: " & giOst & ", готово: " & giz & "%. Выключен." 	end if loop   objTextFileOpen.Close  WScript.Echo "Операция завершена!"  function fuPing(NetworkDevice) 	lBoo = false 	set objPING = GetObject("winmgmts:{impersonationLevel=impersonate}")._ 		ExecQuery ("select * from Win32_PingStatus where address ='" & NetworkDevice & "'")  	For Each PING In objPing 		if PING.StatusCode = 0 then 			'WScript.Echo "* Компьютер " & NetworkDevice & " в сети!"  			lBoo = true 		else 			'WScript.Echo "* Компьютера нет в сети." 		end if 	next 	 	fuPing = lBoo end function  

Запускается процедура проверки bat-файлом. Ссылку на него можно сделать, например, на рабочем столе.

bat-файл

cscript //nologo "f:\Computer\is_computer_online_listComps.vbs" %1 %2 

Основной скрипт is_computer_online_listComps.vbs читает список компьютеров из текстового файла и для каждого запускает bat-файл формирования отчёта. Для XP — это файл is_computer_online.bat, для 7 — is_computer_online7.bat.
Примечание.
На сервере нужно установить logparser.
Всё описанное должно заработать и на компьютере администратора. Только надо установить Microsoft SQL SERVER 2008 NATIVE CLIENT и Microsoft SQL Server 2008 Command Line Utilities. Но я не проверял.

Блок работы с компьютерами XP

Bat-файл:

is_computer_online.bat

cscript //nologo "f:\Computer\is_computer_online.vbs" %1 %2 

Bat-файл запускает скрипт. Скрипт выполняет сохранение событий журнала безопасности в evt-файл и запускает основной батник mo2csv.bat.

is_computer_online.vbs

on error resume next  dim gsComputerName dim gsUseLogFile dim gsLogFilename dim gbFlag  dim gsTableName dim gsCompName dim gsRunCmd  if Wscript.Arguments.Count = 1 then 	gsComputerName = Wscript.Arguments(0) 	gsUseLogFile = "n" elseif Wscript.Arguments.Count = 2 then 	gsComputerName = Wscript.Arguments(0) 	gsUseLogFile = Wscript.Arguments(1) else 	gsComputerName = InputBox("Имя компьютера", "Введите", "") 	gsUseLogFile = InputBox("Использовать log-файл для проверки?" & VBNewline & "[y/n]", "Введите", "y") end if  WScript.Echo "* Имя компьютера " & gsComputerName gsLogFilename = "f:\Log\" & gsComputerName & ".log"  if lCase(gsUseLogFile) = "y" then 	gbFlag = false 	WScript.Echo "* Файл журнала " & gsLogFilename 	set objFSO = CreateObject("Scripting.FileSystemObject")  	if not objFSO.FileExists(gsLogFilename) then 		WScript.Echo "* Файла журнала нет. Создается..." 		set objTextFileWriteLog = objFSO.OpenTextFile(gsLogFilename, 8, True) 		objTextFileWriteLog.writeLine "n" 		objTextFileWriteLog.close 		WScript.Echo "* Создан успешно." 	end if  	set objTextFileOpen = objFSO.OpenTextFile(gsLogFilename, 1) 	do until objTextFileOpen.AtEndOfStream 		record = trim(objTextFileOpen.Readline) 		if record = "n" then 			WScript.Echo "* Компьютер не проверялся ранее." 			if fuPing(gsComputerName) then 				gbFlag = true 				 				if fuBackup(gsComputerName) then 					WScript.Sleep 15000 ' <- 15 секунд задержки для бекапа 					fuUploadEvents gsComputerName 					wscript.sleep 10000 				end if 			end if 		elseif record = "y" then 			WScript.Echo "* Информация с компьютера " & gsComputerName & " уже закачана на сервер." 		else  			WScript.Echo "* Некорректная информация о компьютере " & gsComputerName & " в log-файле." 		end if 	loop  	objTextFileOpen.close  	if gbFlag then 		set objTextFileWriteLog = objFSO.OpenTextFile(gsLogFilename, 2, True) 		objTextFileWriteLog.writeLine "y" 		objTextFileWriteLog.close 		WScript.Echo "* Информация записана в журнал." 	end if else 	'if fuPing(gsComputerName) then 		if fuBackup(gsComputerName) then 			WScript.Sleep 15000 ' <- 15 секунд задержки для бекапа 			fuUploadEvents gsComputerName 			wscript.sleep 10000 		end if 	'end if end if  wscript.sleep 1000  function fuPing(NetworkDevice) 	lBoo = false 	set objPING = GetObject("winmgmts:{impersonationLevel=impersonate}")._ 		ExecQuery ("select * from Win32_PingStatus where address ='" & NetworkDevice & "'")  	For Each PING In objPing 		if PING.StatusCode = 0 then 			WScript.Echo "* Компьютер " & NetworkDevice & " в сети!"  			lBoo = true 		else 			WScript.Echo "* Компьютера нет в сети." 		end if 	next 	 	fuPing = lBoo end function   function fuBackup(lsComputername) 	lsEvtBackupFilename = "c:\" & lsComputername & ".evt" 	lsEvtBackupFilenameRemote = "\\" & lsComputername & "\c$\" & lsComputername & ".evt" 	lbFlag = false 	 	set lObjFSO = CreateObject("Scripting.FileSystemObject") 	 	if lObjFSO.FileExists(lsEvtBackupFilenameRemote) then 		WScript.Echo "* Файл журнала уже есть. Используем существующий..." 		lbFlag = true 	else 		Wscript.Echo "* Выполняется резервное копирование..." 		Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate,(Backup)}!\\" & lsComputername & "\root\cimv2") 		Set colLogFiles = objWMIService.ExecQuery ("Select * from Win32_NTEventLogFile where LogFileName='Security'")  		For Each objLogfile in colLogFiles 			errBackupLog = objLogFile.BackupEventLog(lsEvtBackupFilename) 			If errBackupLog = 0 Then         				Wscript.Echo "* Резервное копирование выполнено успешно." 				lbFlag = true 			Else 				Wscript.Echo "* Резервное копирование не выполнено." 			End If 		Next 	end if 	 	fuBackup = lbFlag end function   function fuUploadEvents(lsComputername) 	WScript.Echo "* Запущена закачка на сервер..." 	gsCompName = lCase(lsComputername)  	gsTableName = fuGetTableName(gsCompName) 	gsTableName = uCase(gsTableName) 	gsOutputFilename = "f:\Computer\" & gsCompName & ".csv" 	gsOutputFilenameSQL = "f:\Computer\" & gsCompName & "_sql.csv"  	Set WshShell = CreateObject("WScript.Shell") 	gsRunCmd = "f:\Computer\mo2csv.bat " & gsCompName & " " & gsOutputFilename & " " & gsOutputFilenameSQL & " " & gsTableName  	WScript.Echo "* Выполняется команда: '" & gsRunCmd & "'" 	WshShell.Run gsRunCmd end function   function fuGetTableName(lsCompName) 	lsTmp = lsCompName 	 	if InStr(lsTmp, "-") then 		lsTmp = Replace(lsTmp, "-", "_") 	end if 	 	fuGetTableName = lsTmp end function  

mo2csv.bat делает следующее:

  • Забирает evt-файл с удалённого компьютера на сервер.
  • Преобразовывает evt-файл в evtx.
  • Выгружает только события запуска/остановки программ из evtx-файла в текстовый файл csv.
  • Информацию из текстового файла закачивает на SQL Server.
  • Бекапит оригинальный evt-файл в папку Logi_ForReports (вдруг пользователь сотрёт свой журнал, а у нас копия есть).
  • Удаляет временный evtx-файл.
  • Формирует и выполняет sql-запрос к SQL Server’у.
  • Удаляет временные файлы (в случае отладки или для изучения работы скрипта, этот раздел можно закомментировать).
  • Перемещает отчёты в папку CheckComps.

mo2csv.bat

@echo off  @set WDate=%date:~-10%  @echo * Журнал безопасности перемещается с удаленного компьютера %1 (Windows XP)... move \\%1\c$\%1.evt f:\Logs\ @echo * Перемещение завершено.  @echo * Выполняется конвертация evt журнала в evtx... wevtutil epl f:\Logs\%1.evt f:\Logs\%1.evtx /lf:true @echo * Конвертация завершена.  @echo * Информация из журнала безопасности выгружается в текстовый файл. Источник: f:\Logs\%1.evtx, назначение: %2 LogParser.exe file:"f:\Computer\get_info_from_log.sql"?source=f:\Logs\%1.evtx+output_file=%2 -i:EVT -o:TSV -headers:ON -oSeparator:tab -oTsFormat:"dd.MM.yyyy hh:mm:ss" -fileMode:1 @echo * Выгрузка завершена.  @echo * Исправляю текстовый файл %2. Получаю %3... cscript F:\Computer\update_csvFile_forSQLCheck.vbs %2 %3 //NoLogo @echo * Исправление завершено.   @echo * Информация из текстового файла закачивается на SQL Server. Источник: %3, таблица %4... LogParser.exe file:"f:\Computer\get_info_from_log_2SQL.sql"?source=%3+output_file=%4 -i:TSV -headerRow:ON -iSeparator:tab -iTsFormat:"dd.MM.yyyy hh:mm:ss" -o:SQL -server:"SQL-SRV\SEC" -database:quickly -driver:"SQL Server" -createTable:ON @echo * Процесс завершен.   @echo * Журнал безопасности перемещается в архив... move f:\Logs\%1.evt f:\Logi_ForReports\%1_%WDate%_sec.evt @echo * Перемещение завершено. Имя архивного файла 'f:\Logi_ForReports\%1_%WDate%_sec.evt'  @echo * Удаление временного evtx журнала... del f:\Logs\%1.evtx @echo * Удаление завершено.   @echo * Создание sql-запроса... cscript "F:\Computer\create_SQL_full.vbs" %1 1 //nologo @echo * Создание завершено.  @echo * Выполнение sql-запроса... SQLCMD.EXE -S SQL-SRV\SEC -d quickly -E -i f:\Computer\%1-1.sql -o "f:\Computer\%1. Запуск программ.csv" -W -R -s ";" -w 4000 @echo * Выполнение завершено.  @echo * Исправляю результирующие файлы отчетов... cscript F:\Computer\update_result_file.vbs "f:\Computer\%1. Запуск программ.csv" //nologo @echo * Исправление завершено.  @echo * Удаление временных файлов... del f:\Computer\%1-1.sql del %2 del %3 del f:\Computer\%1_dbg.txt del "f:\Computer\%1. Запуск программ.csv" @echo * Удаление завершено.  @echo * Перемещение файлов-отчетов... move "f:\Computer\%1. Запуск программ.xls" "f:\CheckComps\%1. Запуск программ.xls" @echo * Перемещение завершено.  @echo on 

Примечание
Возможно, в батнике нужно будет SQLCMD.EXE заменить на «c:\Program Files\Microsoft SQL Server\100\Tools\Binn\SQLCMD.EXE», а LogParser.exe на «c:\Program Files (x86)\Log Parser 2.2\LogParser.exe» (или «c:\Program Files\Log Parser 2.2\LogParser.exe»).
Имя сервера с SQL Server’ом SQL-SRV, имя экземпляра SEC и имя базы quickly. Заменить на свои.

get_info_from_log.sql

SELECT RecordNumber as id,  	eventid as eId,  	TimeGenerated as Tg,  	resolve_sid(sid) as UserName,  	computername as Computer,  	EXTRACT_TOKEN(Strings, 0, '|') as image_unique_id, 	EXTRACT_TOKEN(Strings, 1, '|') as image into %output_file%  FROM %source% where ((EventID in (592; 593)) and (TO_UPPERCASE(resolve_sid(sid)) <> 'NT AUTHORITY\NETWORK SERVICE') and (TO_UPPERCASE(resolve_sid(sid)) <> 'NT AUTHORITY\SYSTEM')) and TimeGenerated >= TO_TIMESTAMP('01.03.2011 00:00:00','dd.MM.yyyy hh:mm:ss') order by recordnumber asc 

get_info_from_log_2SQL.sql

SELECT * into %output_file%  FROM %source% 

update_csvFile_forSQLCheck.vbs

On Error Resume Next  dim gsSimbolSplitFields dim sgSimbolSplitAdmin dim gbInsideBlock dim gIx dim gbDebug dim gbWriteString  Dim gArrBlock_admin  gsSimbolSplitFields = vbTab sgSimbolSplitAdmin = ";" gbInsideBlock = false gbIERuning = false gbIE = false giBlockPlus = 0 giIEPlus = 0 gsDateBlock = "01.01.2011 00:00:00" TgBlockStop = "01.01.2011 00:00:00" idBlockStop = "" gIx = 0 gArrBlock_admin = Array (sgSimbolSplitAdmin & sgSimbolSplitAdmin, _ 	sgSimbolSplitAdmin & sgSimbolSplitAdmin, _ 	sgSimbolSplitAdmin & sgSimbolSplitAdmin, _ 	sgSimbolSplitAdmin & sgSimbolSplitAdmin) gbDebug = true 'gbDebug = false  if Wscript.Arguments.Count = 1 then 	sgFilename = Wscript.Arguments(0) 	sgFilenameOut = fuRemoveExtention(sgFilename) & "_sql.csv" 	gsLogFilename = fuRemoveExtention(sgFilename) & "_dbg.txt" elseif Wscript.Arguments.Count = 2 then 	sgFilename = Wscript.Arguments(0) 	sgFilenameOut = Wscript.Arguments(1) 	gsLogFilename = fuRemoveExtention(sgFilename) & "_dbg.txt" elseif Wscript.Arguments.Count = 3 then 	sgFilename = Wscript.Arguments(0) 	sgFilenameOut = Wscript.Arguments(1) 	gsLogFilename = Wscript.Arguments(2) else 	sgFilename = InputBox("Имя исходного файла", "Введите", "f:\comp-6475.csv") 	sgFilenameOut = InputBox("Имя результирующего файла", "Введите", fuRemoveExtention(sgFilename) & "_sql.csv") 	gsLogFilename = InputBox("Имя файла журнала", "Введите", fuRemoveExtention(sgFilename) & "_dbg.txt") end if  Set objFSO = CreateObject("Scripting.FileSystemObject")  if not objFSO.FileExists(sgFilename) then 	wscript.echo "Исходного файла для обновления нет, выхожу!" 	Wscript.Quit end if  Set objTextFileOpen = objFSO.OpenTextFile(sgFilename, 1) Set objTextFileWrite = objFSO.CreateTextFile(sgFilenameOut, True)  if gbDebug then 	if not objFSO.FileExists(gsLogFilename) then 		set objTextFileWriteLog = objFSO.OpenTextFile(gsLogFilename, 8, True) 	else 		set objTextFileWriteLog = objFSO.CreateTextFile(gsLogFilename, True) 	end if end if 	 Do Until objTextFileOpen.AtEndOfStream 	record = trim(objTextFileOpen.Readline) 	gIx = gIx + 1 	gbWriteString = true 	fuPrint gIx & ". '" & record & "'" 	 	if InStr(record, gsSimbolSplitFields) then 		arr = Split(record, gsSimbolSplitFields) 		id = arr(0) 		eId = arr(1) 		Tg = arr(2) 		UserName = arr(3) 		Computer = arr(4) 		image_unique_id = arr(5) 		image = arr(6) 		 		if InStr(lCase(image), "explorer.exe") then 			if eId = "592" then 				gbBlockBegin = true 				gbBlockEnd = false 				giBlockPlus = giBlockPlus + 1 				fuPrint "explorer.exe старт" 			else  				gbBlockBegin = false 				gbBlockEnd = true 				giBlockPlus = giBlockPlus - 1 				if giBlockPlus < 0 then 					giBlockPlus = 0 				end if 				fuPrint	"explorer.exe стоп" 			end if 		else 			gbBlockBegin = false 			gbBlockEnd = false 		end if 		 		if InStr(lCase(image), "iexplore.exe") then 			gbIE = true 			fuPrint	"Строка с iexplore.exe" 			 			if eId = "592" then 				fuPrint	"iexplore.exe старт" 				giIEPlus = giIEPlus + 1 				gbIERuning = true 				 				if giIEPlus = 1 then 					image_unique_idIEStart = image_unique_id 				end if 			else  				fuPrint	"iexplore.exe стоп" 				giIEPlus = giIEPlus - 1 				gbIERuning = false 			end if 		else  			gbIE = false 			fuPrint	"Строка без iexplore.exe" 		end if 		 		if gIx = 1 then 			objTextFileWrite.WriteLine record & gsSimbolSplitFields & "CompStart" 			fuPrint "Первая строка, записываем" 		elseif gIx = 2 then 			fuPrint "вторая строка" 			if gbBlockBegin then 				fuPrint "Начало блока, записываем" 				gbInsideBlock = true 				gsDateBlock = Tg 				gsUserNameBlockStart = UserName 				image_unique_idBlockStart = image_unique_id 				objTextFileWrite.WriteLine record & gsSimbolSplitFields & gsDateBlock 			end if 			 			idPrev = id 			eIdPrev = eId 			TgPrev = Tg 			UserNamePrev = UserName 			ComputerPrev = Computer 			image_unique_idPrev = image_unique_id 			imagePrev = image	 		else 			'fuPrint "остальные строки" 			 			'-- Запуск explorer.exe 			if gbBlockBegin then 				fuPrint "Запуск explorer.exe (экземпляр № " & giBlockPlus & ")" 				 				if giBlockPlus = 1 then 					giDiff = DateDiff("s", CDate(TgBlockStop), CDate(Tg)) 					if giDiff > 9 then 						if Len(idBlockStop) > 0 then 							fuPrint "Это не перезапуск explorer.exe. Записываем остановку предыдущего блока" 							record_convert_prev = idBlockStop & gsSimbolSplitFields & _ 									eIdBlockStop & gsSimbolSplitFields & _ 									TgBlockStop & gsSimbolSplitFields & _ 									UserNameBlockStop & gsSimbolSplitFields & _ 									ComputerBlockStop & gsSimbolSplitFields & _ 									image_unique_idBlockStart & gsSimbolSplitFields & _ 									imageBlockStop & gsSimbolSplitFields & _ 									gsDateBlock 							fuPrint record_convert_prev 							objTextFileWrite.WriteLine record_convert_prev 						end if 						 						gsDateBlock = Tg 						fuPrint "Новая дата блока: '" & gsDateBlock & "'" 						image_unique_idBlockStart = image_unique_id 						fuPrint "Новый код блока: '" & image_unique_idBlockStart & "'" 						gsUserNameBlockStart = UserName 						fuPrint "Новый пользователь блока: '" & gsUserNameBlockStart & "'" 					else 						fuPrint "Это перезапуск explorer.exe! Не записываем остановку предыдущего блока и не записываем запуск этого." 						gbWriteString = false 					end if 					 					gbInsideBlock = true 				else 					if lCase(gsUserNameBlockStart) = lCase(UserName) then 						fuPrint "gsUserNameBlockStart: '" & gsUserNameBlockStart & "', UserName: '" & UserName & "'" 						fuPrint "Начало блока. Возможно, компьютер был аварийно выключен. Необходимо записать окончание предыдущего блока и сохранить новые параметры блока" 						record_convert_prev = "999" & gsSimbolSplitFields & _ 								"593" & gsSimbolSplitFields & _ 								Tg & gsSimbolSplitFields & _ 								UserName & gsSimbolSplitFields & _ 								Computer & gsSimbolSplitFields & _ 								image_unique_idBlockStart & gsSimbolSplitFields & _ 								"C:\WINDOWS\explorer.exe" & gsSimbolSplitFields & _ 								gsDateBlock 						fuPrint record_convert_prev 						objTextFileWrite.WriteLine record_convert_prev 						 						giBlockPlus = 1 						 						gsDateBlock = Tg 						fuPrint "Новая дата блока: '" & gsDateBlock & "'" 						image_unique_idBlockStart = image_unique_id 						fuPrint "Новый код блока: '" & image_unique_idBlockStart & "'" 					else 						'fuPrint "gsUserNameBlockStart: '" & gsUserNameBlockStart & "', UserName: '" & UserName & "'" 						fuPrint "Не начало блока. Возможно, администратор запустил explorer. Записать текущую строку и сохранить параметры" 						gArrBlock_admin(giBlockPlus-2) = image_unique_id & sgSimbolSplitAdmin & UserName & sgSimbolSplitAdmin & Tg 						fuPrint gArrBlock_admin(giBlockPlus-2) 						'gsDateBlock_admin = Tg 						objTextFileWrite.WriteLine record & gsSimbolSplitFields & Tg 						gbWriteString = false 					end if 				end if 			end if 			 			'-- Остановка explorer.exe 			if gbBlockEnd then 				fuPrint "Остановлен explorer.exe (осталось экземпляров " & giBlockPlus & ")" 				 				if giBlockPlus = 0 then 					fuPrint "Остановлен последний экземпляр, сохраняем его значения" 					 					idBlockStop = id 					eIdBlockStop = eId 					TgBlockStop = Tg 					UserNameBlockStop = UserName 					ComputerBlockStop = Computer 					image_unique_idBlockStop = image_unique_id 					imageBlockStop = image 					 					gbInsideBlock = false 					giIEPlus = 0 ' <-- Добавил для обнуления количества копий IE 				else 					fuPrint "Остановлен не последний экземпляр, его значения не сохраняем, только записываем текущую строку"		 					for giY = 0 to UBound(gArrBlock_admin) 						arrA = Split(gArrBlock_admin(giY), sgSimbolSplitAdmin) 						gsImage_unique_id_A = arrA(0) 						gsUserName_A = arrA(1) 						gsTg_A = arrA(2) 						 						if gsImage_unique_id_A = image_unique_id then 							gsDateBlock_admin = gsTg_A 						end if 					next 					objTextFileWrite.WriteLine record & gsSimbolSplitFields & gsDateBlock_admin 					gbWriteString = false 				end if 			end if 			 			'-- Записать текущую строку  			if gbInsideBlock then 				if gbIE then 					if (((gbIERuning) and (giIEPlus = 1)) or ((not gbIERuning) and (giIEPlus = 0))) then 						fuPrint "Записать IE строку" 						record_convert_prev = id & gsSimbolSplitFields & _ 							eId & gsSimbolSplitFields & _ 							Tg & gsSimbolSplitFields & _ 							UserName & gsSimbolSplitFields & _ 							Computer & gsSimbolSplitFields & _ 							image_unique_idIEStart & gsSimbolSplitFields & _ 							image & gsSimbolSplitFields & _ 							gsDateBlock 						fuPrint record_convert_prev 						objTextFileWrite.WriteLine record_convert_prev 					else 						fuPrint "Вот хрень с IE! gbIERuning: " & gbIERuning & ", giIEPlus: " & giIEPlus 						record_convert_prev = id & gsSimbolSplitFields & _ 							eId & gsSimbolSplitFields & _ 							Tg & gsSimbolSplitFields & _ 							UserName & gsSimbolSplitFields & _ 							Computer & gsSimbolSplitFields & _ 							image_unique_idIEStart & gsSimbolSplitFields & _ 							image & gsSimbolSplitFields & _ 							gsDateBlock 						fuPrint record_convert_prev 					end if 				else 					if gbWriteString then 						fuPrint "Текущая строка в блоке и ее нужно записать" 						fuPrint record & gsSimbolSplitFields & gsDateBlock 						objTextFileWrite.WriteLine record & gsSimbolSplitFields & gsDateBlock 					else 						fuPrint "Текущая строка в блоке, но ее записывать не нужно" 					end if 				end if 			else 				fuPrint "Текущая строка не в блоке. Не записываем" 			end if  			'-- Сохранить текущие значения параметров для следующего прохода  			idPrev = id 			eIdPrev = eId 			TgPrev = Tg 			UserNamePrev = UserName 			ComputerPrev = Computer 			image_unique_idPrev = image_unique_id 			imagePrev = image 		end if 	end if 	fuPrint "----------------------------------------------" Loop  objTextFileWrite.Close objTextFileOpen.Close  if gbDebug then 	objTextFileWriteLog.close end if  WScript.Echo "" WScript.Echo "* Операция успешно завершена."    function fuRemoveExtention(lsFilename) 	lRes = lsFilename 	if InStr(lsFilename, ".") then 		lRes = Left(lsFilename, Len(lsFilename)-4) 	end if 	fuRemoveExtention = lRes end function   function fuGetDateFromFullDate(lsFullDate) 	lRes = lsFullDate 	if InStr(lsFullDate, " ") then 		lArr = Split(lsFullDate, " ") 		lsDate = lArr(0) 		lsTime = lArr(1) 		lRes = lsDate 	end if 	fuGetDateFromFullDate = lRes end function   function fuGetTimeFromFullDate(lsFullDate) 	lRes = lsFullDate 	if InStr(lsFullDate, " ") then 		lArr = Split(lsFullDate, " ") 		lsDate = lArr(0) 		lsTime = lArr(1) 		lRes = lsTime 	end if 	fuGetDateFromFullDate = lRes end function   function fuPrint(lsStr) 	'if gbDebug then 	'	wscript.echo lsStr 	'end if 	 	if gbDebug then 		objTextFileWriteLog.writeLine lsStr 	end if 	 	fuPrint = true end function  

create_SQL_full.vbs

if Wscript.Arguments.Count = 1 then 	gsComputerName = Wscript.Arguments(0) 	gsSQLtype = "1" elseif Wscript.Arguments.Count = 2 then 	gsComputerName = Wscript.Arguments(0) 	gsSQLtype = Wscript.Arguments(1) else 	gsComputerName = InputBox("Имя компьютера", "Введите", "") 	gsSQLtype = InputBox("Тип sql-запроса?" & VBNewline & "[1 - короткий, 2 - полный, 3 - оба]", "Введите", "1") end if  set objFSO = CreateObject("Scripting.FileSystemObject")  if gsSQLtype = "1" then 	fuCreateSQLFile gsComputerName, "1" elseif gsSQLtype = "2" then 	fuCreateSQLFile gsComputerName, "2" elseif gsSQLtype = "3" then 	fuCreateSQLFile gsComputerName, "1" 	fuCreateSQLFile gsComputerName, "2" end if  function fuGetTableName(lsCompName) 	lsTmp = lsCompName 	 	if InStr(lsTmp, "-") then 		lsTmp = Replace(lsTmp, "-", "_") 	end if 	 	fuGetTableName = lsTmp end function   sub fuCreateSQLFile(lsComputerName, lsSQLtype) 	if lsSQLtype = "1" then 		lsTemplateFilename = "f:\Computer\template-short.sql" 	elseif gsSQLtype = "2" then 		lsTemplateFilename = "f:\Computer\template-full.sql" 	end if 	 	lsLogFilename = "f:\Computer\" & lsComputerName & "-" & lsSQLtype & ".sql" 	lsTableName = fuGetTableName(lsComputerName)  	if not objFSO.FileExists(lsLogFilename) then 		set objTextFileWriteLog = objFSO.OpenTextFile(lsLogFilename, 8, True) 	else 		set objTextFileWriteLog = objFSO.OpenTextFile(lsLogFilename, 2, True) 	end if 	 	Set objTextFileOpen = objFSO.OpenTextFile(lsTemplateFilename, 1) 	 	do until objTextFileOpen.AtEndOfStream 		record = objTextFileOpen.Readline 		if InStr(record, "WARNING__TABLE_NAME_FOR_CHANGE") then 			record = Replace(record, "WARNING__TABLE_NAME_FOR_CHANGE", lsTablename) 		end if 		objTextFileWriteLog.writeLine record 	loop   	objTextFileOpen.Close 	objTextFileWriteLog.Close end sub  

template-short.sql

SELECT     TOP (100) PERCENT Computer AS [Имя компьютера], UserName AS [Учетная запись], image AS Программа, start_time AS [Время запуска],                        stop_time AS [Время завершения], dbo.FU_GET_FULL_QTY_TEST(CONVERT(VARCHAR, DATEDIFF(SECOND, start_time, stop_time) / 3600))                        + ':' + dbo.FU_GET_FULL_QTY_TEST(CONVERT(VARCHAR, DATEDIFF(SECOND, start_time, stop_time) % 3600 / 60))                        + ':' + dbo.FU_GET_FULL_QTY_TEST(CONVERT(VARCHAR, DATEDIFF(SECOND, start_time, stop_time) % 3600 % 60)) AS Длительность FROM         (SELECT     r.Computer, r.UserName, r.image_unique_id, r.image, r.Tg AS start_time, MIN(s.Tg) AS stop_time                        FROM          (SELECT     id, eId, Tg, UserName, Computer, image_unique_id, image                                                FROM          dbo.WARNING__TABLE_NAME_FOR_CHANGE                                                WHERE      (eId = 592) AND (Tg > CONVERT(DATETIME, '2013-01-01 00:00:00.000', 102))                                                ) AS r INNER JOIN                                                   (SELECT     id, eId, Tg, UserName, Computer, image_unique_id, image                                                     FROM          dbo.WARNING__TABLE_NAME_FOR_CHANGE                                                     WHERE      (eId = 593)) AS s ON r.image_unique_id = s.image_unique_id AND r.image = s.image AND r.id < s.id AND r.Tg <= s.Tg                        GROUP BY r.UserName, r.Computer, r.image_unique_id, r.image, r.Tg) AS DERIVEDTBL ORDER BY 'Время запуска' DESC 

update_result_file.vbs

if Wscript.Arguments.Count = 1 then 	gsFileName = Wscript.Arguments(0) 	gsFileNameRes = fuRemoveExtention(gsFileName) & ".xls" elseif Wscript.Arguments.Count = 2 then 	gsFileName = Wscript.Arguments(0) 	gsFileNameRes = Wscript.Arguments(1) else 	gsFileName = InputBox("Файл для обновления", "Ввод", "") 	gsFileNameRes = InputBox("Файл результата", "Ввод", fuRemoveExtention(gsFileName) & ".xls") end if  sgSimbolSplit = ";" gsSimbolSplitFields = vbTab  Set objFSO = CreateObject("Scripting.FileSystemObject") Set objTextFileOpen = objFSO.OpenTextFile(gsFileName, 1)  if not objFSO.FileExists(gsFileName) then 	wscript.echo "Исходного файла для обновления нет, выхожу!" 	objTextFileOpen.Close 	Wscript.Quit end if  if not objFSO.FileExists(gsFileNameRes) then 	set objTextFileWriteRes = objFSO.OpenTextFile(gsFileNameRes, 8, True) else 	set objTextFileWriteRes = objFSO.CreateTextFile(gsFileNameRes, True) end if  do until objTextFileOpen.AtEndOfStream 	record = objTextFileOpen.Readline 	 	if ((InStr(record, "--------")) or (Len(record) = 0) or (InStr(record, "обработано строк")) or (InStr(record, "rows affected"))) then 		'wscript.echo "пропускаю строку: '" & record & "'" 	else 		if InStr(record, sgSimbolSplit) then 			recordRes = Replace(record, sgSimbolSplit, gsSimbolSplitFields) 		else 			recordRes = record 		end if 		 		objTextFileWriteRes.writeLine recordRes 	end if loop   objTextFileWriteRes.Close objTextFileOpen.Close  WScript.Echo "Обновление завершено! Результирующий файл " & gsFileNameRes  function fuRemoveExtention(lsFilename) 	lRes = lsFilename 	if InStr(lsFilename, ".") then 		lRes = Left(lsFilename, Len(lsFilename)-4) 	end if 	fuRemoveExtention = lRes end function  

Блок работы с компьютерами с семёркой

Bat-файл:

is_computer_online7.bat

cscript //nologo "f:\Computer\is_computer_online7.vbs" %1 %2 

Bat-файл запускает скрипт. Скрипт выполняет сохранение событий журнала безопасности в evt-файл и запускает основной батник mo7.bat.

is_computer_online7.vbs

on error resume next  dim gsComputerName dim gsUseLogFile dim gsLogFilename dim gbFlag  dim gsTableName dim gsCompName dim gsRunCmd   if Wscript.Arguments.Count = 1 then 	gsComputerName = Wscript.Arguments(0) 	gsUseLogFile = "n" elseif Wscript.Arguments.Count = 2 then 	gsComputerName = Wscript.Arguments(0) 	gsUseLogFile = Wscript.Arguments(1) else 	gsComputerName = InputBox("Имя компьютера", "Введите", "") 	gsUseLogFile = InputBox("Использовать log-файл для проверки?" & VBNewline & "[y/n]", "Введите", "y") end if  WScript.Echo "* Имя компьютера " & gsComputerName  if lCase(gsUseLogFile) = "y" then 	gbFlag = false 	 	gsLogFilename = "f:\Log\" & gsComputerName & ".log"  	WScript.Echo "* Файл журнала " & gsLogFilename  	set objFSO = CreateObject("Scripting.FileSystemObject")  	if not objFSO.FileExists(gsLogFilename) then 		WScript.Echo "* Файла журнала нет. Создается..." 		set objTextFileWriteLog = objFSO.OpenTextFile(gsLogFilename, 8, True) 		objTextFileWriteLog.writeLine "n" 		objTextFileWriteLog.close 		WScript.Echo "* Создан успешно." 	end if  	set objTextFileOpen = objFSO.OpenTextFile(gsLogFilename, 1)  	do until objTextFileOpen.AtEndOfStream 		record = trim(objTextFileOpen.Readline) 		if record = "n" then 			WScript.Echo "* Компьютер не проверялся ранее." 			if fuPing(gsComputerName) then 				'fuListInstalledSoftware gsComputerName 				gbFlag = true 				 				if fuBackup(gsComputerName) then 					WScript.Sleep 15000 ' <- 15 секунд задержки для бекапа 					fuUploadEvents gsComputerName 					wscript.sleep 10000 				end if 			end if 		elseif record = "y" then 			WScript.Echo "* Информация с компьютера " & gsComputerName & " уже закачана на сервер." 		else  			WScript.Echo "* Некорректная информация о компьютере " & gsComputerName & " в log-файле." 		end if 	loop  	objTextFileOpen.close  	if gbFlag then 		set objTextFileWriteLog = objFSO.OpenTextFile(gsLogFilename, 2, True) 		objTextFileWriteLog.writeLine "y" 		objTextFileWriteLog.close 		WScript.Echo "* Информация записана в журнал." 		 		'MsgBox "Компьютер " & gsComputerName & " в сети!", vbInformation, "Внимание" 	end if else 	'if fuPing(gsComputerName) then 		if fuBackup(gsComputerName) then 			WScript.Sleep 15000 ' <- 15 секунд задержки для бекапа 			fuUploadEvents gsComputerName 			wscript.sleep 60000 		end if 	'end if end if  wscript.sleep 1000  function fuPing(NetworkDevice) 	lBoo = false 	set objPING = GetObject("winmgmts:{impersonationLevel=impersonate}")._ 		ExecQuery ("select * from Win32_PingStatus where address ='" & NetworkDevice & "'")  	For Each PING In objPing 		if PING.StatusCode = 0 then 			WScript.Echo "* Компьютер " & NetworkDevice & " в сети!"  			lBoo = true 		else 			WScript.Echo "* Компьютера нет в сети." 		end if 	next 	 	fuPing = lBoo end function   function fuBackup(lsComputername) 	lsEvtBackupFilename = "c:\" & lsComputername & ".evt" 	lsEvtBackupFilenameRemote = "\\" & lsComputername & "\c$\" & lsComputername & ".evt" 	lbFlag = false 	 	'WScript.Echo "* lsEvtBackupFilename: " & lsEvtBackupFilename 	'WScript.Echo "* lsEvtBackupFilenameRemote: " & lsEvtBackupFilenameRemote 	 	set lObjFSO = CreateObject("Scripting.FileSystemObject") 	 	if lObjFSO.FileExists(lsEvtBackupFilenameRemote) then 		WScript.Echo "* Файл журнала уже есть. Используем существующий..." 		lbFlag = true 	else 		Wscript.Echo "* Выполняется резервное копирование..." 		 		Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate,(Backup)}!\\" & lsComputername & "\root\cimv2")  		Set colLogFiles = objWMIService.ExecQuery ("Select * from Win32_NTEventLogFile where LogFileName='Security'")  		For Each objLogfile in colLogFiles 			errBackupLog = objLogFile.BackupEventLog(lsEvtBackupFilename) 			If errBackupLog = 0 Then         				Wscript.Echo "* Резервное копирование выполнено успешно." 				lbFlag = true 			Else 				Wscript.Echo "* Резервное копирование не выполнено." 			End If 		Next 	end if 	 	fuBackup = lbFlag end function   function fuUploadEvents(lsComputername) 	WScript.Echo "* Запущена закачка на сервер..." 	gsCompName = lCase(lsComputername)  	gsTableName = fuGetTableName(gsCompName) 	gsTableName = uCase(gsTableName)   	Set WshShell = CreateObject("WScript.Shell")  	gsRunCmd = "f:\Computer\mo7.bat " & gsCompName & " " & gsTableName  	WScript.Echo "* Выполняется команда: '" & gsRunCmd & "'" 	WshShell.Run gsRunCmd end function   function fuGetTableName(lsCompName) 	lsTmp = lsCompName 	 	if InStr(lsTmp, "-") then 		lsTmp = Replace(lsTmp, "-", "_") 	end if 	 	fuGetTableName = lsTmp end function   

mo7.bat делает следующее:

  • Забирает evt-файл с удалённого компьютера на сервер.
  • Преобразовывает evt-файл в evtx.
  • Информацию из evtx-файла закачивает на SQL Server.
  • Бекапит оригинальный evt-файл в папку Logi_ForReports (вдруг пользователь сотрёт свой журнал, а у нас копия есть).
  • Удаляет временный evtx-файл.
  • Формирует и выполняет sql-запрос к SQL Server’у.
  • Удаляет временные файлы (в случае отладки или для изучения работы скрипта, этот раздел можно закомментировать).
  • Перемещает отчёты в папку CheckComps.

mo7.bat

@echo off  @set WDate=%date:~-10%  @echo * Журнал безопасности перемещается с удаленного компьютера %1 (Windows 7)... move \\%1\c$\%1.evt f:\Logs\ @echo * Перемещение завершено.  @echo * Выполняется конвертация evt журнала в evtx... wevtutil epl f:\Logs\%1.evt f:\Logs\%1.evtx /lf:true @echo * Конвертация завершена.  @echo * Информация из журнала безопасности закачивается на сервер. Источник: f:\Logs\%1.evtx LogParser.exe file:"f:\Computer\get_info_from_log7.sql"?source=f:\Logs\%1.evtx+output_file=%2 -i:EVT -o:SQL -server:"SQL-SRV\SEC" -database:quickly -driver:"SQL Server" -createTable:ON @echo * Процесс завершен.  @echo * Журнал безопасности перемещается в архив... move f:\Logs\%1.evt f:\Logi_ForReports\%1_%WDate%_sec.evt @echo * Перемещение завершено. Имя архивного файла 'f:\Logi_ForReports\%1_%WDate%_sec.evtx'   @echo * Создание sql-запроса... cscript "F:\Computer\create_SQL_full7.vbs" %1 1 //nologo @echo * Создание завершено.  @echo * Выполнение sql-запроса... SQLCMD.EXE -S SQL-SRV\SEC -d quickly -E -i f:\Computer\%1-1.sql -o "f:\Computer\%1. Запуск программ.csv" -W -R -s ";" -w 4000 @echo * Выполнение завершено.  @echo * Исправляю результирующие файлы отчетов... cscript F:\Computer\update_result_file7.vbs "f:\Computer\%1. Запуск программ.csv" //nologo @echo * Исправление завершено.  @echo * Удаление временных файлов... del f:\Logs\%1.evtx del f:\Computer\%1-1.sql del "f:\Computer\%1. Запуск программ.csv" @echo * Удаление временных файлов завершено.  @echo * Перемещение файлов-отчетов... move "f:\Computer\%1. Запуск программ.xls" "f:\CheckComps\%1. Запуск программ.xls" @echo * Перемещение завершено.  @echo on 

Примечание
Возможно, в батнике нужно будет SQLCMD.EXE заменить на «c:\Program Files\Microsoft SQL Server\100\Tools\Binn\SQLCMD.EXE», а LogParser.exe на «c:\Program Files (x86)\Log Parser 2.2\LogParser.exe» (или «c:\Program Files\Log Parser 2.2\LogParser.exe»).
Имя сервера с SQL Server’ом SQL-SRV, имя экземпляра SEC и имя базы quickly. Заменить на свои.

get_info_from_log7.sql

SELECT RecordNumber as id,  	eventid as eId,  	TimeGenerated as Tg,  	--resolve_sid(sid) as UserName,  	EXTRACT_TOKEN(Strings, 1, '|') as UserName, 	computername as Computer,  	EXTRACT_TOKEN(Strings, 4, '|') as image_id, 	EXTRACT_TOKEN(Strings, 5, '|') as image, 	EXTRACT_TOKEN(Strings, 6, '|') as name into %output_file%  FROM %source% where (EventID in (4688;4689)) and ( (TO_UPPERCASE(resolve_sid(sid)) <> 'NT AUTHORITY\NETWORK SERVICE') and (TO_UPPERCASE(resolve_sid(sid)) <> 'NT AUTHORITY\SYSTEM')) and TimeGenerated >= TO_TIMESTAMP('01.01.2013 00:00:00','dd.MM.yyyy hh:mm:ss') order by recordnumber desc 

create_SQL_full7.vbs

'on error resume next  if Wscript.Arguments.Count = 1 then 	gsComputerName = Wscript.Arguments(0) 	gsSQLtype = "1" elseif Wscript.Arguments.Count = 2 then 	gsComputerName = Wscript.Arguments(0) 	gsSQLtype = Wscript.Arguments(1) else 	gsComputerName = InputBox("Имя компьютера", "Введите", "") 	gsSQLtype = InputBox("Тип sql-запроса?" & VBNewline & "[1 - короткий, 2 - полный, 3 - оба]", "Введите", "1") end if  set objFSO = CreateObject("Scripting.FileSystemObject")  if gsSQLtype = "1" then 	fuCreateSQLFile gsComputerName, "1" elseif gsSQLtype = "2" then 	fuCreateSQLFile gsComputerName, "2" elseif gsSQLtype = "3" then 	fuCreateSQLFile gsComputerName, "1" 	fuCreateSQLFile gsComputerName, "2" end if  function fuGetTableName(lsCompName) 	lsTmp = lsCompName 	 	if InStr(lsTmp, "-") then 		lsTmp = Replace(lsTmp, "-", "_") 	end if 	 	fuGetTableName = lsTmp end function   sub fuCreateSQLFile(lsComputerName, lsSQLtype) 	if lsSQLtype = "1" then 		lsTemplateFilename = "f:\Computer\template-short7.sql" 	elseif gsSQLtype = "2" then 		lsTemplateFilename = "f:\Computer\template-full7.sql" 	end if 	 	lsLogFilename = "f:\Computer\" & lsComputerName & "-" & lsSQLtype & ".sql" 	lsTableName = fuGetTableName(lsComputerName)  	'WScript.Echo "* Имя компьютера " & lsComputerName 	'WScript.Echo "* Имя таблицы " & lsTableName 	'WScript.Echo "* Имя файла sql-запроса " & lsLogFilename  	if not objFSO.FileExists(lsLogFilename) then 		set objTextFileWriteLog = objFSO.OpenTextFile(lsLogFilename, 8, True) 	else 		set objTextFileWriteLog = objFSO.OpenTextFile(lsLogFilename, 2, True) 	end if 	 	Set objTextFileOpen = objFSO.OpenTextFile(lsTemplateFilename, 1) 	 	do until objTextFileOpen.AtEndOfStream 		record = objTextFileOpen.Readline 		if InStr(record, "WARNING__TABLE_NAME_FOR_CHANGE") then 			record = Replace(record, "WARNING__TABLE_NAME_FOR_CHANGE", lsTablename) 		end if 		objTextFileWriteLog.writeLine record 	loop   	objTextFileOpen.Close 	objTextFileWriteLog.Close end sub  

template-short7.sql

SELECT TOP (100) PERCENT Computer AS [Имя компьютера], UserName AS [Учетная запись], program AS Программа, start_time AS [Время запуска],         stop_time AS [Время завершения], dbo.FU_GET_FULL_QTY_TEST(CONVERT(VARCHAR, DATEDIFF(SECOND, start_time, stop_time) / 3600))         + ':' + dbo.FU_GET_FULL_QTY_TEST(CONVERT(VARCHAR, DATEDIFF(SECOND, start_time, stop_time) % 3600 / 60))         + ':' + dbo.FU_GET_FULL_QTY_TEST(CONVERT(VARCHAR, DATEDIFF(SECOND, start_time, stop_time) % 3600 % 60)) AS Длительность FROM   (SELECT r.Computer, s.UserName, r.programID, r.id AS R_ID, MIN(s.id) AS S_ID, r.program, r.Tg AS start_time, MIN(s.Tg) AS stop_time         FROM   (SELECT  id, eId, Tg, UserName, Computer, image_id AS programID, image AS program 				FROM    dbo.WARNING__TABLE_NAME_FOR_CHANGE 				WHERE   (eId = 4688) 				AND     (Tg > CONVERT(DATETIME, '2013-01-01 00:00:00.000', 102)) 				AND     image not like '%.scr') AS r  				INNER JOIN 				(SELECT  id, eId, Tg, UserName, Computer, image AS programID, name AS program 				FROM    dbo.WARNING__TABLE_NAME_FOR_CHANGE 				WHERE   (eId = 4689) 				AND     name not like '%.scr') AS s  				ON r.programID = s.programID AND r.program = s.program AND r.UserName = s.UserName AND r.id <= s.id          GROUP BY r.Computer, s.UserName, r.programID, r.id, r.program, r.Tg) AS DERIVEDTBL UNION ALL SELECT  TOP (100) PERCENT Computer AS [Имя компьютера], UserName AS [Учетная запись], program AS Программа, start_time AS [Время запуска],          stop_time AS [Время завершения], dbo.FU_GET_FULL_QTY_TEST(CONVERT(VARCHAR, DATEDIFF(SECOND, start_time, stop_time) / 3600))          + ':' + dbo.FU_GET_FULL_QTY_TEST(CONVERT(VARCHAR, DATEDIFF(SECOND, start_time, stop_time) % 3600 / 60))          + ':' + dbo.FU_GET_FULL_QTY_TEST(CONVERT(VARCHAR, DATEDIFF(SECOND, start_time, stop_time) % 3600 % 60)) AS Длительность FROM    (SELECT r.Computer, s.UserName, r.programID, r.id AS R_ID, MIN(s.id) AS S_ID, r.program, r.Tg AS start_time, MIN(s.Tg) AS stop_time          FROM   (SELECT  id, eId, Tg, UserName, Computer, image_id AS programID, image AS program 				 FROM    dbo.WARNING__TABLE_NAME_FOR_CHANGE                  WHERE   (eId = 4688)                  AND     (Tg > CONVERT(DATETIME, '2013-01-01 00:00:00.000', 102)) 				 AND     image like '%.scr') AS r  				 INNER JOIN                 (SELECT  id, eId, Tg, UserName, Computer, image AS programID, name AS program                  FROM    dbo.WARNING__TABLE_NAME_FOR_CHANGE                  WHERE   (eId = 4689) 				 AND     name like '%.scr') AS s  				 ON r.programID = s.programID AND r.program = s.program AND r.id <= s.id          GROUP BY r.Computer, s.UserName, r.programID, r.id, r.program, r.Tg) AS DERIVEDTBL2 ORDER BY 'Время запуска' DESC  

update_result_file7.vbs

'on error resume next  if Wscript.Arguments.Count = 1 then 	gsFileName = Wscript.Arguments(0) 	gsFileNameRes = fuRemoveExtention(gsFileName) & ".xls" elseif Wscript.Arguments.Count = 2 then 	gsFileName = Wscript.Arguments(0) 	gsFileNameRes = Wscript.Arguments(1) else 	gsFileName = InputBox("Файл для обновления", "Ввод", "") 	gsFileNameRes = InputBox("Файл результата", "Ввод", fuRemoveExtention(gsFileName) & ".xls") end if  sgSimbolSplit = ";" gsSimbolSplitFields = vbTab  Set objFSO = CreateObject("Scripting.FileSystemObject") Set objTextFileOpen = objFSO.OpenTextFile(gsFileName, 1)  if not objFSO.FileExists(gsFileName) then 	wscript.echo "Исходного файла для обновления нет, выхожу!" 	objTextFileOpen.Close 	Wscript.Quit end if  if not objFSO.FileExists(gsFileNameRes) then 	set objTextFileWriteRes = objFSO.OpenTextFile(gsFileNameRes, 8, True) else 	set objTextFileWriteRes = objFSO.CreateTextFile(gsFileNameRes, True) end if  do until objTextFileOpen.AtEndOfStream 	record = objTextFileOpen.Readline 	 	if ((InStr(record, "--------")) or (Len(record) = 0) or (InStr(record, "обработано строк")) or (InStr(record, "rows affected"))) then 		'wscript.echo "пропускаю строку: '" & record & "'" 	else 		if InStr(record, sgSimbolSplit) then 			recordRes = Replace(record, sgSimbolSplit, gsSimbolSplitFields) 		else 			recordRes = record 		end if 		 		objTextFileWriteRes.writeLine recordRes 	end if loop   objTextFileWriteRes.Close objTextFileOpen.Close  WScript.Echo "Обновление завершено! Результирующий файл " & gsFileNameRes  function fuRemoveExtention(lsFilename) 	lRes = lsFilename 	if InStr(lsFilename, ".") then 		lRes = Left(lsFilename, Len(lsFilename)-4) 	end if 	fuRemoveExtention = lRes end function  

На SQL Server’е надо создать функцию FU_GET_FULL_QTY_TEST:

FU_GET_FULL_QTY_TEST

USE [quickly] GO /****** Object:  UserDefinedFunction [dbo].[FU_GET_FULL_QTY_TEST]    Script Date: 12/03/2013 13:03:43 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO  CREATE FUNCTION [dbo].[FU_GET_FULL_QTY_TEST] (@short_qty varchar(255)) RETURNS varchar(255) AS BEGIN DECLARE @retMsg varchar(255) set @retMsg = @short_qty if len(@short_qty) <= 1 set @retMsg = '0' + @retMsg RETURN (@retMsg) END 

Архив со скриптами можно скачать тут.
Знаю, кажется много батников и скриптов. Но достаточно один раз настроить и пользоваться потом.

И кто как делает отчёт по запуску программ на компьютерах пользователей? Поделитесь.

ссылка на оригинал статьи http://habrahabr.ru/post/202914/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *