Что нового

Мониторинг файловой системы

pvnn

Осваивающий
Сообщения
305
Репутация
32
Добрый день!
Как можно осуществить мониторинг определенного каталога с подкаталогами на файловом сервере.
Необходим лог создания (удаления, изменения) файлов и каталогов с указанием имен пользователей.

Недавно была тема: Найти новый файл в папке (http://autoit-script.ru/index.php?topic=6426.0),
где AZJIO предложил решение при помощи UDF - FileSystemMonitor
(http://www.autoitscript.com/forum/index.php?showtopic=113560&st=0)

Данный пример

Код:
#include <GUIConstants.au3>
#include <GUIConstantsEx.au3>
#include <ListviewConstants.au3>
#Include <GuiListView.au3>
#include <WindowsConstants.au3>
#include <FileSystemMonitor.au3>

dim $msg

; GUI Setup

$main_gui = GUICreate("Shell Notification Monitor (Press ESC to close)", 800, 320, -1, -1, -1, $WS_EX_TOPMOST)
$path_input = GUICtrlCreateInput("C:\", 10, 10, 320)
$use_path_button = GUICtrlCreateButton("Use Path", 350, 10)
$listview = GUICtrlCreateListView("", 10, 40, 780, 250, $LVS_REPORT)
_GUICtrlListView_SetUnicodeFormat($listview, False)
_GUICtrlListView_InsertColumn($listview, 0, "Type", 200)
_GUICtrlListView_InsertColumn($listview, 1, "Name (Hex)", 200)
_GUICtrlListView_InsertColumn($listview, 2, "Value", 200)
_GUICtrlListView_InsertColumn($listview, 3, "Time", 100)
GUISetState(@SW_SHOW)

; Setup File System Monitoring
_FileSysMonSetup(3, "C:\", "")

; Main Loop

While 1

	; Handle Directory related events
	_FileSysMonDirEventHandler()

	If $msg = $use_path_button then 

		_FileSysMonSetDirMonPath(GUICtrlRead($path_input))
		_FileSysMonSetShellMonPath(GUICtrlRead($path_input))
	EndIf

	If $msg = $GUI_EVENT_CLOSE then 
		
		ExitLoop
	EndIf

	$msg = GUIGetMsg()
WEnd

Func _FileSysMonActionEvent($event_type, $event_id, $event_value)

	Local $event_type_name
	Local $fs_event = ObjCreate("Scripting.Dictionary")

	Switch $event_type
		
		Case 0

			$fs_event.item(Hex(0x00000001)) = "file added to the directory|FILE_ACTION_ADDED"
			$fs_event.item(Hex(0x00000002)) = "file removed from the directory|FILE_ACTION_REMOVED"
			$fs_event.item(Hex(0x00000003)) = "file was modified|FILE_ACTION_MODIFIED"
			$fs_event.item(Hex(0x00000004)) = "file was renamed old name|FILE_ACTION_RENAMED_OLD_NAME"
			$fs_event.item(Hex(0x00000005)) = "file was renamed new name|FILE_ACTION_RENAMED_NEW_NAME"

		Case 1

			$fs_event.item(Hex(0x00000001)) = "Non-folder item name changed|SHCNE_RENAMEITEM"
			$fs_event.item(Hex(0x00000002)) = "Non-folder item created|SHCNE_CREATE"
			$fs_event.item(Hex(0x00000004)) = "Non-folder item deleted|SHCNE_DELETE"
			$fs_event.item(Hex(0x00000008)) = "Folder created|SHCNE_MKDIR"
			$fs_event.item(Hex(0x00000010)) = "Folder removed|SHCNE_RMDIR"
			$fs_event.item(Hex(0x00000020)) = "Storage media inserted into a drive|SHCNE_MEDIAINSERTED"
			$fs_event.item(Hex(0x00000040)) = "Storage media removed from a drive|SHCNE_MEDIAREMOVED"
			$fs_event.item(Hex(0x00000080)) = "Drive removed|SHCNE_DRIVEREMOVED"
			$fs_event.item(Hex(0x00000100)) = "Drive added|SHCNE_DRIVEADD"
			$fs_event.item(Hex(0x00000200)) = "Local computer folder shared via the network|SHCNE_NETSHARE"
			$fs_event.item(Hex(0x00000400)) = "Local computer folder not shared via the network|SHCNE_NETUNSHARE"
			$fs_event.item(Hex(0x00000800)) = "Item or folder attributes have changed|SHCNE_ATTRIBUTES"
			$fs_event.item(Hex(0x00001000)) = "Folder content has changed|SHCNE_UPDATEDIR"
			$fs_event.item(Hex(0x00002000)) = "Folder or non-folder has changed|SHCNE_UPDATEITEM"
			$fs_event.item(Hex(0x00004000)) = "Computer disconnected from server|SHCNE_SERVERDISCONNECT"
			$fs_event.item(Hex(0x00008000)) = "System image list image has changed|SHCNE_UPDATEIMAGE"
			$fs_event.item(Hex(0x00010000)) = "Not used|SHCNE_DRIVEADDGUI"
			$fs_event.item(Hex(0x00020000)) = "Folder name has changed|SHCNE_RENAMEFOLDER"
			$fs_event.item(Hex(0x00040000)) = "Drive free space has changed|SHCNE_FREESPACE"
			$fs_event.item(Hex(0x0002381F)) = "SHCNE_DISKEVENTS"
			$fs_event.item(Hex(0x0C0581E0)) = "SHCNE_GLOBALEVENTS"
			$fs_event.item(Hex(0x7FFFFFFF)) = "SHCNE_ALLEVENTS"
			$fs_event.item(Hex(0x80000000)) = "SHCNE_INTERRUPT"
	EndSwitch
	
	if StringLen($fs_event.item(Hex($event_id))) > 0 Then
	
		$event_type_name = StringSplit($fs_event.item(Hex($event_id)), "|")
		$event_type_name[2] = $event_type_name[2] & "(" & $event_id & ")"
		
		_GUICtrlListView_InsertItem($listview, $event_type_name[1], 0)
		_GUICtrlListView_SetItemText($listview, 0, $event_type_name[2], 1)
		_GUICtrlListView_SetItemText($listview, 0, $event_value, 2)
		_GUICtrlListView_SetItemText($listview, 0, @HOUR & ":" & @MIN & ":" & @SEC, 3)
	EndIf
EndFunc

запустил на файловом сервере и выявилось 2 проблемы:
1. При создании файлов/каталогов текущем пользователем данные отображаются корректно:
Folder created, при создании другим пользователем: Folder content has changed -
т.е. нет конкретики.
2. Как добавить имена пользователей, которые производили изменения файлов/каталогов.

Может быть у кого-то уже есть готовые наработки?
 

Scampy

Новичок
Сообщения
50
Репутация
0
Может не совсем то, но недавно нашел вот это:
Код:
#cs ----------------------------------------------------------------------------

 AutoIt Version: 3.2.10.0
 Author:         zorphnog (M. Mims)

 Script Function:
    Monitors the user defined directories for file activity.

#ce ----------------------------------------------------------------------------


#include <Constants.au3>
#include <WinAPI.au3>
#include <Date.au3>
#include <GUIConstants.au3>
#include <GuiListBox.au3>
#include <GuiListView.au3>

Global Const _
        $FILE_FLAG_BACKUP_SEMANTICS = 0x02000000, _
        $FILE_FLAG_OVERLAPPED       = 0x40000000
Global Const _
        $FILE_NOTIFY_CHANGE_ALL         = 0x17F, _
        $FILE_NOTIFY_CHANGE_FILE_NAME   = 0x001, _
        $FILE_NOTIFY_CHANGE_DIR_NAME    = 0x002, _
        $FILE_NOTIFY_CHANGE_ATTRIBUTES  = 0x004, _
        $FILE_NOTIFY_CHANGE_SIZE        = 0x008, _
        $FILE_NOTIFY_CHANGE_LAST_WRITE  = 0x010, _
        $FILE_NOTIFY_CHANGE_LAST_ACCESS = 0x020, _
        $FILE_NOTIFY_CHANGE_CREATION    = 0x040, _
        $FILE_NOTIFY_CHANGE_SECURITY    = 0x100
Global Const _
        $FILE_ACTION_ADDED            = 0x1, _
        $FILE_ACTION_REMOVED          = 0x2, _
        $FILE_ACTION_MODIFIED         = 0x3, _
        $FILE_ACTION_RENAMED_OLD_NAME = 0x4, _
        $FILE_ACTION_RENAMED_NEW_NAME = 0x5
Global Const _
        $MWMO_ALERTABLE      = 0x0002, _
        $MWMO_INPUTAVAILABLE = 0x0004, _
        $MWMO_WAITALL        = 0x0001
Global Const $FILE_LIST_DIRECTORY = 0x0001
Global Const $QS_ALLINPUT = 0x04FF
Global Const $INFINITE = 0xFFFF
Global Const $tagFNIIncomplete = "dword NextEntryOffset;dword Action;dword FileNameLength"
Global $bMonitorDone, $bSelected, $bMonitor
AutoItSetOption("GUIOnEventMode", 1)

$gFileMon = GUICreate("Directory Monitor", 731, 385, 194, 126)
GUISetOnEvent($GUI_EVENT_CLOSE, "_OnEvent_Close")
GUICtrlCreateGroup("Monitored Directories", 8, 0, 713, 105)
$btAdd = GUICtrlCreateButton("Add", 16, 24, 75, 25, 0)
GUICtrlSetOnEvent(-1, "_OnEvent_Add")
$btRemove = GUICtrlCreateButton("Remove", 16, 56, 75, 25, 0)
GUICtrlSetOnEvent(-1, "_OnEvent_Remove")
GUICtrlSetState(-1, $GUI_DISABLE)
$lbDirectories = GUICtrlCreateList("", 104, 16, 506, 71)
$btMonitor = GUICtrlCreateButton("Start Monitor", 632, 24, 75, 25, 0)
GUICtrlSetOnEvent(-1, "_OnEvent_Monitor")
GUICtrlSetState(-1, $GUI_DISABLE)
$btClear = GUICtrlCreateButton("Clear", 632, 56, 75, 25, 0)
GUICtrlSetOnEvent(-1, "_OnEvent_Clear")
GUICtrlCreateGroup("", -99, -99, 1, 1)
$lvNotifications = GUICtrlCreateListView("Action|Time|File", 8, 112, 714, 262)
GUICtrlSendMsg(-1, 0x101E, 0, Int(.1*710))
GUICtrlSendMsg(-1, 0x101E, 1, Int(.2*710))
GUICtrlSendMsg(-1, 0x101E, 2, Int(.7*710)-20)
GUISetState(@SW_SHOW)

_Main()

Func _DisplayFileMessages($hBuffer, $sDir)
    Local $hFileNameInfo, $pBuffer, $hTime
    Local $nFileNameInfoOffset = 12, $nOffset = 0, $nNext = 1
    $pBuffer = DllStructGetPtr($hBuffer)
    While $nNext <> 0
        $hFileNameInfo = DllStructCreate($tagFNIIncomplete, $pBuffer + $nOffset)
        $hFileName = DllStructCreate("wchar FileName[" & DllStructGetData($hFileNameInfo, "FileNameLength")/2 & "]", $pBuffer + $nOffset + $nFileNameInfoOffset)
        $hTime = _Date_Time_GetSystemTime()
        Switch DllStructGetData($hFileNameInfo, "Action")
            Case $FILE_ACTION_ADDED
                _GUICtrlListView_InsertItem($lvNotifications, "Created", 0)
            Case $FILE_ACTION_REMOVED
                _GUICtrlListView_InsertItem($lvNotifications, "Deleted", 0)
            Case $FILE_ACTION_MODIFIED
                _GUICtrlListView_InsertItem($lvNotifications, "Modified", 0)
            Case $FILE_ACTION_RENAMED_OLD_NAME
                _GUICtrlListView_InsertItem($lvNotifications, "Rename-", 0)
            Case $FILE_ACTION_RENAMED_NEW_NAME
                _GUICtrlListView_InsertItem($lvNotifications, "Rename+", 0)
            Case Else
                _GUICtrlListView_InsertItem($lvNotifications, "Unknown", 0)
        EndSwitch
        _GUICtrlListView_AddSubItem($lvNotifications, 0, _Date_Time_SystemTimeToDateTimeStr($hTime), 1)
        _GUICtrlListView_AddSubItem($lvNotifications, 0, $sDir & DllStructGetData($hFileName, "FileName"), 2)
        $nNext = DllStructGetData($hFileNameInfo, "NextEntryOffset")
        $nOffset += $nNext
    WEnd
EndFunc

Func _GetBufferHandle ()
    Return DllStructCreate("ubyte[2048]")
EndFunc

Func _GetDirectoryChanges($aDirHandles, $hBuffer, $aOverlapped, $hEvents, $aDirs, $bAsync = Default, $nTimeout = Default)
    Local $aMsg, $i, $nBytes = 0
    If $nTimeout = -1 Or IsKeyword($nTimeout) Then $nTimeout = 250
    If Not $bAsync Then $nTimeout = $INFINITE
    $aMsg = DllCall("User32.dll", "dword", "MsgWaitForMultipleObjectsEx", _
        "dword", UBound($aOverlapped), _
        "ptr", DllStructGetPtr($hEvents), _
        "dword", $nTimeout, _
        "dword", 0, _
        "dword", 0x6)
    $i = $aMsg[0]
    Switch $i
        Case 0 To UBound($aDirHandles)-1
            If Not _WinAPI_GetOverlappedResult($aDirHandles[$i], DllStructGetPtr($aOverlapped[$i]), $nBytes, True) Then
                ConsoleWrite("!>  GetOverlappedResult Error(" & @error & "): " & _WinAPI_GetLastErrorMessage() & @LF)
                Return 0
            EndIf
            DllCall("Kernel32.dll", "Uint", "ResetEvent", "uint", DllStructGetData($aOverlapped[$i], "hEvent"))
            _DisplayFileMessages($hBuffer, $aDirs[$i])
            _SetReadDirectory($aDirHandles[$i], $hBuffer, $aOverlapped[$i],False,True)
            Return $nBytes
    EndSwitch
    Return 0
EndFunc

Func _GetDirHandle($sDir)
    Local $aResult
    $aResult = DllCall("Kernel32.dll", "hwnd", "CreateFile", _
        "str", $sDir, _
        "int", $FILE_LIST_DIRECTORY, _
        "int", BitOR($FILE_SHARE_DELETE,$FILE_SHARE_READ,$FILE_SHARE_WRITE), _
        "ptr", 0, _
        "int", $OPEN_EXISTING, _
        "int", BitOR($FILE_FLAG_BACKUP_SEMANTICS,$FILE_FLAG_OVERLAPPED), _
        "int", 0)
    If $aResult[0] = 0 Then
        ConsoleWrite("!>  CreateFile Error (" & @error & "): " & _WinAPI_GetLastErrorMessage() & @LF)
        Exit
    EndIf
    Return $aResult[0]
EndFunc

Func _GetEventHandles ($aOverlapped)
    Local $i, $hEvents
    $hEvents = DllStructCreate("hwnd hEvent[" & UBound($aOverlapped) & "]")
    For $i=1 To UBound($aOverlapped)
        DllStructSetData($hEvents, "hEvent", DllStructGetData($aOverlapped[$i-1], "hEvent"), $i)
    Next
    Return $hEvents
EndFunc

Func _GetOverlappedHandle ()
    Local $hOverlapped = DllStructCreate($tagOVERLAPPED)
    For $i=1 To 5
        DllStructSetData($hOverlapped, $i, 0)
    Next
    Return $hOverlapped
EndFunc

Func _Main ()
    $bSelected = False
    $bMonitorDone = True
    $bMonitor = False
    While 1
        If Not $bMonitorDone Then _MonitorDirs()
        If $bMonitor And _GUICtrlListBox_GetCount($lbDirectories) = 0 Then
            $bMonitor = Not $bMonitor
            GUICtrlSetState($btMonitor, $GUI_DISABLE)
        ElseIf Not $bMonitor And _GUICtrlListBox_GetCount($lbDirectories) > 0 Then
            $bMonitor = Not $bMonitor
            GUICtrlSetState($btMonitor, $GUI_ENABLE)
        EndIf
        If $bSelected And _GUICtrlListBox_GetCurSel($lbDirectories) = -1 Then
            $bSelected = Not $bSelected
            GUICtrlSetState($btRemove, $GUI_DISABLE)
        ElseIf Not $bSelected And _GUICtrlListBox_GetCurSel($lbDirectories) <> -1 Then
            $bSelected = Not $bSelected
            GUICtrlSetState($btRemove, $GUI_ENABLE)
        EndIf
    WEnd
EndFunc

Func _MonitorDirs ()
    Local $i, $nMax, $hBuffer, $hEvents
    $nMax = _GUICtrlListBox_GetCount($lbDirectories)
    Local $aDirHandles[$nMax], $aOverlapped[$nMax], $aDirs[$nMax]
    $hBuffer = _GetBufferHandle()
    For $i = 0 To $nMax-1
        $aDirs[$i] = _GUICtrlListBox_GetText($lbDirectories, $i)
        $aDirHandles[$i] = _GetDirHandle($aDirs[$i])
        $aOverlapped[$i] = _GetOverlappedHandle()
        _SetReadDirectory($aDirHandles[$i], $hBuffer, $aOverlapped[$i], True, True)
    Next
    $hEvents = _GetEventHandles($aOverlapped)
    While Not $bMonitorDone
        _GetDirectoryChanges($aDirHandles, $hBuffer, $aOverlapped, $hEvents, $aDirs)
    WEnd
EndFunc

Func _OnEvent_Add ()
    Local $sDir, $nMax, $i
    $sDir = FileSelectFolder("Select directory to monitor", "")
    If $sDir <> "" Then
        If StringRight($sDir, 1) <> "\" Then $sDir &= "\"
        $nMax = _GUICtrlListBox_GetCount($lbDirectories)-1
        For $i = 0 To $nMax
            If _GUICtrlListBox_GetText($lbDirectories, $i) = $sDir Then Return
        Next
        _GUICtrlListBox_AddString($lbDirectories, $sDir)
    EndIf
EndFunc

Func _OnEvent_Clear ()
    _GUICtrlListView_DeleteAllItems(GUICtrlGetHandle($lvNotifications))
EndFunc

Func _OnEvent_Close ()
    Exit
EndFunc

Func _OnEvent_Monitor ()
    If $bMonitorDone Then
        $bMonitorDone = False
        GUICtrlSetData($btMonitor, "Stop Monitor")
        GUICtrlSetState($btAdd, $GUI_DISABLE)
        GUICtrlSetState($btRemove, $GUI_DISABLE)
        GUICtrlSetState($lbDirectories, $GUI_DISABLE)
        $bSelected = False
    Else
        $bMonitorDone = True
        GUICtrlSetState($lbDirectories, $GUI_ENABLE)
        GUICtrlSetState($btAdd, $GUI_ENABLE)
        GUICtrlSetData($btMonitor, "Start Monitor")
    EndIf
EndFunc

Func _OnEvent_Remove ()
    _GUICtrlListBox_DeleteString($lbDirectories, _GUICtrlListBox_GetCurSel($lbDirectories))
EndFunc

Func _SetReadDirectory($hDir, $hBuffer, $hOverlapped, $bInitial = False, $bSubtree = False)
    Local $hEvent, $pBuffer, $nBufferLength, $pOverlapped
    $pBuffer = DllStructGetPtr($hBuffer)
    $nBufferLength = DllStructGetSize($hBuffer)
    $pOverlapped = DllStructGetPtr($hOverlapped)
    If $bInitial Then
        $hEvent = DllCall("Kernel32.dll", "hwnd", "CreateEvent", _
            "uint", 0, _
            "int", True, _
            "int", False, _
            "uint", 0)
        If $hEvent[0] = 0 Then
            ConsoleWrite("!>  CreateEvent Failed (" & _WinAPI_GetLastError() & "): " & _WinAPI_GetLastErrorMessage() & @LF)
            Exit
        EndIf
        DllStructSetData($hOverlapped, "hEvent", $hEvent[0])
    EndIf
    $aResult = DllCall("Kernel32.dll", "int", "ReadDirectoryChangesW", _
        "hwnd", $hDir, _
        "ptr", $pBuffer, _
        "dword", $nBufferLength, _
        "int", $bSubtree, _
        "dword", BitOR($FILE_NOTIFY_CHANGE_FILE_NAME, _
            $FILE_NOTIFY_CHANGE_SIZE,$FILE_NOTIFY_CHANGE_DIR_NAME), _
        "uint", 0, _
        "uint", $pOverlapped, _
        "uint", 0)
    If $aResult[0] = 0 Then
        ConsoleWrite("!>  ReadDirectoryChangesW Error(" & @error & "): " & _WinAPI_GetLastErrorMessage() & @LF)
        Exit
    EndIf
    Return $aResult[0]
EndFunc
 
Автор
P

pvnn

Осваивающий
Сообщения
305
Репутация
32
Scampy, да 1 часть проблемы решена. Проверил создание, редактирование, удаление разными пользователями - мониторится нормально. Вот теперь как узнать имена этих пользователей, которые производили изменения файлов/каталогов
 

labudator

Новичок
Сообщения
25
Репутация
0
Извините но скрипт както не работает. копирую на диск С файлы, но вместо того чтоб показать что такой то файл появился там то, в окне выдается сообдение типа Folder or non-Folder has cahged
 
Верх