PDA

Показать полную графическую версию : [решено] Контроль изменения файлов


support23
22-10-2012, 11:44
Доброго дня!
Есть задача: Необходимо контролировать файлы (расширения разные - dll, xml, ini и т.д.) в заданной папке, на предмет их удаления, добавления новых, изменения существующих. И отражать это в лог файле (дата, время, какие были изменения - например удален файл name.exe, изменен файл name.ini)
Как это можно реализовать?

Iska
22-10-2012, 14:06
support23, файлов только в самой папке? Без учёта вложенных в неё папок?

support23
22-10-2012, 15:05
support23, файлов только в самой папке? Без учёта вложенных в неё папок? »
Да, вложенных папок нет.

266903582
22-10-2012, 18:31
Получаем список файлов (_FileListToArray,FileFindFirstFile,FileFindNextFile)
Пишем его в файл (например ini)
С нужной периодичностью получаем текущий список и для каждого файла сравниваем со старым списком. Так отсеиваем появление/исчезнвение файлов.
Для каждого файла считаем контрольную сумму (_CRC32()), пишем ее туда-же в ini файл в раздел с именем данного файла. Так сможем отслеживать реальные изменения файлов.
Для отслеживания дат изменения используем информацию из атрибутов (FileGetAttrib (),FileGetTime ()), пишем ее рядом с контрольной суммой.
Определять конкретные изменения в файлах уже сложнее, тут уже от типов файлов зависит...

Iska
23-10-2012, 02:29
support23, пробуйте:
#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_UseUpx=n
#AutoIt3Wrapper_Change2CUI=y
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****

#include <file.au3>
#Include <Date.au3>
#Include <WinAPI.au3>
#Include <Crypt.au3>

AutoItSetOption("MustDeclareVars", 1)

Local $sFolder = "e:\Песочница\0190"

Local $sComputer = "."
Local $oSWbemLocator = ObjCreate("WbemScripting.SWbemLocator")
Local $oSWbemServicesEx = $oSWbemLocator.ConnectServer($sComputer, "root\cimv2")
Local $oSWbemSink = ObjCreate("WbemScripting.SWbemSink")
Local $oSink = ObjEvent($oSWbemSink, "Sink_")

Local $aSplitPath, $sDrive, $sDir, $sFileName, $sExtension
Local $dtNow, $sNow

Local $sMD5
Local $oDictionary = ObjCreate("Scripting.Dictionary")


_PathSplit($sFolder & "\", $sDrive, $sDir, $sFileName, $sExtension)

$oSWbemServicesEx.ExecNotificationQueryAsync($oSWbemSink, _
"SELECT * FROM __InstanceOperationEvent WITHIN 1 WHERE " & _
"TargetInstance ISA 'CIM_DataFile' AND " & _
"TargetInstance.Drive = '" & $sDrive & "' AND " & _
"TargetInstance.Path = '" & StringReplace($sDir, "\", "\\") & "'" _
)

_Crypt_Startup()

Do
Sleep(100)
Until(False)

_Crypt_Shutdown()

$oDictionary.RemoveAll

$oDictionary = 0
$oSink = 0
$oSWbemSink = 0
$oSWbemServicesEx = 0
$oSWbemLocator = 0

Exit(0)

Func Sink_OnObjectReady($oSWbemObjectEx, $oSWbemAsyncContext)
With $oSWbemObjectEx
$dtNow = _Date_Time_GetLocalTime()
$sNow = _Date_Time_SystemTimeToDateTimeStr($dtNow, 1)

Select
Case .Path_.Class = "__InstanceCreationEvent"
$sMD5 = _Crypt_HashFile(.TargetInstance.Name, $CALG_MD5)

$oDictionary.Add(.TargetInstance.Name, $sMD5)
ConsoleWrite($sNow & _WinAPI_WideCharToMultiByte(" |  | Create: [" & .TargetInstance.Name, 1) & "]" & @CRLF)
Case .Path_.Class = "__InstanceModificationEvent"
$sMD5 = _Crypt_HashFile(.TargetInstance.Name, $CALG_MD5)

If $oDictionary.Exists(.TargetInstance.Name) Then
If $oDictionary.Item(.TargetInstance.Name) <> $sMD5 Then
$oDictionary.Item(.TargetInstance.Name) = $sMD5
ConsoleWrite($sNow & _WinAPI_WideCharToMultiByte(" |  | Modify: [" & .TargetInstance.Name, 1) & "]" & @CRLF)
EndIf
Else
$oDictionary.Add(.TargetInstance.Name, $sMD5)
ConsoleWrite($sNow & _WinAPI_WideCharToMultiByte(" | ± | Modify: [" & .TargetInstance.Name, 1) & "]" & @CRLF)
EndIf
Case .Path_.Class = "__InstanceDeletionEvent"
$oDictionary.Remove(.TargetInstance.Name)
ConsoleWrite($sNow & _WinAPI_WideCharToMultiByte(" |  | Delete: [" & .TargetInstance.Name, 1) & "]" & @CRLF)
Case Else
; Nothing to do
EndSelect
EndWith
EndFunc

AZJIO
23-10-2012, 05:58
FileSystemMonitor (http://www.autoitscript.com/forum/index.php?showtopic=113560&st=0)
http://autoit-script.ru/index.php/topic,6426.0.html - Если поискать найдётся ещё несколько тем.

support23
23-10-2012, 15:28
support23, пробуйте: »
Спасибо за предложенный вариант, есть несколько недостатков - не понимает русские имена файлов, при переименовании файла в папке, завершает работу с ошибкой, и желательно чтобы был лог

Iska
23-10-2012, 16:11
support23, что означает:
не понимает русские имена файлов »
?

Это:
при переименовании файла в папке, завершает работу с ошибкой »
посмотрю.

и желательно чтобы был лог »
Перенаправьте вывод в файл.

support23
23-10-2012, 16:24
1. файл checkdir - копия (2).exe при выполнении в консоли отображается как checkdir - Є®ЇЁп (2).exe ( | Create: [e:\test\checkdir - Є®ЇЁп (2).xml])
2. спасибо
3. для этого недостаточно знаний, к сожалению

Iska
24-10-2012, 01:18
1. файл checkdir - копия (2).exe при выполнении в консоли отображается как checkdir - Є®ЇЁп (2).exe ( | Create: [e:\test\checkdir - Є®ЇЁп (2).xml]) »

http://img703.imageshack.us/img703/9012/image00020121024011007.png

Попробуйте использовать TrueType-шрифт для окна консоли.

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

http://img525.imageshack.us/img525/6326/image00020121024011348.png

Перенаправьте вывод в файл. »
3. для этого недостаточно знаний, к сожалению »
bla-bla-bla.exe >Log.txt

support23
26-10-2012, 09:10
Есть несколько файлов в каталоге
E:\Open
Скрипт запускаю на выполнение из Autoit (F5)
при удалении файла из каталога E:\Open получаю ошибку

>"C:\Program Files\AutoIt3\SciTE\..\autoit3.exe" /ErrorStdOut "E:\Test\mont.au3"
E:\Test\mont.au3 (79) : ==> The requested action with this object has failed.:
$oDictionary.Remove(.TargetInstance.Name)
$oDictionary.Remove(.TargetInstance.Name)^ ERROR

Iska
26-10-2012, 18:48
support23, скомпилируйте скрипт и исполняйте скомпилированный файл.

support23
29-10-2012, 12:54
скомпилировал файл, запустил, при переименовании уже существующего файла в папке получаю такую ошибку:

http://forum.oszone.net/attachment.php?attachmentid=89234&stc=1&d=1351500780

Iska
29-10-2012, 22:31
support23, кажется, я понял: у Вас уже существуют файлы в каталоге перед запуском скрипта. И один из них, после запуска скрипта, Вы пытаетесь удалить. Так?

support23
30-10-2012, 08:53
support23, кажется, я понял: у Вас уже существуют файлы в каталоге перед запуском скрипта. И один из них, после запуска скрипта, Вы пытаетесь удалить. Так? »
да, всё верно!

Iska
30-10-2012, 09:25
Надо будет при запуске заполнять словарь существующими файлами. Пробуйте:
#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_UseUpx=n
#AutoIt3Wrapper_Change2CUI=y
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****

#include <file.au3>
#Include <Date.au3>
#Include <WinAPI.au3>
#Include <Crypt.au3>

AutoItSetOption("MustDeclareVars", 1)

Local $sFolder = "e:\Песочница\0190\0001"

Local $sComputer = "."
Local $oSWbemLocator = ObjCreate("WbemScripting.SWbemLocator")
Local $oSWbemServicesEx = $oSWbemLocator.ConnectServer($sComputer, "root\cimv2")
Local $oSWbemObjectEx
Local $oSWbemSink = ObjCreate("WbemScripting.SWbemSink")
Local $oSink = ObjEvent($oSWbemSink, "Sink_")

Local $aSplitPath, $sDrive, $sDir, $sFileName, $sExtension
Local $dtNow, $sNow

Local $sMD5
Local $oDictionary = ObjCreate("Scripting.Dictionary")


_PathSplit($sFolder & "\", $sDrive, $sDir, $sFileName, $sExtension)

$dtNow = _Date_Time_GetLocalTime()
$sNow = _Date_Time_SystemTimeToDateTimeStr($dtNow, 1)

For $oSWbemObjectEx In $oSWbemServicesEx.ExecQuery( _
"SELECT * FROM CIM_DataFile WHERE " & _
"Drive = '" & $sDrive & "' AND " & _
"Path = '" & StringReplace($sDir, "\", "\\") & "'" _
)
$sMD5 = _Crypt_HashFile($oSWbemObjectEx.Name, $CALG_MD5)

$oDictionary.Add($oSWbemObjectEx.Name, $sMD5)
ConsoleWrite($sNow & _WinAPI_WideCharToMultiByte(" |  | Present: [" & $oSWbemObjectEx.Name, 1) & "]" & @CRLF)
Next

$oSWbemServicesEx.ExecNotificationQueryAsync($oSWbemSink, _
"SELECT * FROM __InstanceOperationEvent WITHIN 1 WHERE " & _
"TargetInstance ISA 'CIM_DataFile' AND " & _
"TargetInstance.Drive = '" & $sDrive & "' AND " & _
"TargetInstance.Path = '" & StringReplace($sDir, "\", "\\") & "'" _
)

_Crypt_Startup()

Do
Sleep(100)
Until(False)

_Crypt_Shutdown()

$oDictionary.RemoveAll

$oDictionary = 0
$oSink = 0
$oSWbemSink = 0
$oSWbemServicesEx = 0
$oSWbemLocator = 0

Exit(0)

Func Sink_OnObjectReady($oSWbemObjectEx, $oSWbemAsyncContext)
With $oSWbemObjectEx
$dtNow = _Date_Time_GetLocalTime()
$sNow = _Date_Time_SystemTimeToDateTimeStr($dtNow, 1)

Select
Case .Path_.Class = "__InstanceCreationEvent"
$sMD5 = _Crypt_HashFile(.TargetInstance.Name, $CALG_MD5)

$oDictionary.Add(.TargetInstance.Name, $sMD5)
ConsoleWrite($sNow & _WinAPI_WideCharToMultiByte(" |  | Create: [" & .TargetInstance.Name, 1) & "]" & @CRLF)
Case .Path_.Class = "__InstanceModificationEvent"
$sMD5 = _Crypt_HashFile(.TargetInstance.Name, $CALG_MD5)

If $oDictionary.Exists(.TargetInstance.Name) Then
If $oDictionary.Item(.TargetInstance.Name) <> $sMD5 Then
$oDictionary.Item(.TargetInstance.Name) = $sMD5
ConsoleWrite($sNow & _WinAPI_WideCharToMultiByte(" |  | Modify: [" & .TargetInstance.Name, 1) & "]" & @CRLF)
EndIf
Else
$oDictionary.Add(.TargetInstance.Name, $sMD5)
ConsoleWrite($sNow & _WinAPI_WideCharToMultiByte(" | ± | Modify: [" & .TargetInstance.Name, 1) & "]" & @CRLF)
EndIf
Case .Path_.Class = "__InstanceDeletionEvent"
$oDictionary.Remove(.TargetInstance.Name)
ConsoleWrite($sNow & _WinAPI_WideCharToMultiByte(" |  | Delete: [" & .TargetInstance.Name, 1) & "]" & @CRLF)
Case Else
; Nothing to do
EndSelect
EndWith
EndFunc

support23
31-10-2012, 09:36
Благодарю! работает отлично!




© OSzone.net 2001-2012