Process Monitor

  • Hallo :)

    Meine Frage bezieht sich nicht direkt auf AutoIt und die Überschrift ist auch nicht sehr treffend aber hoffentlich kann mir jemand bei folgendem Problem helfen.
    Ich wollte folgendes machen: Sobald eine Datei umbenannt wird, soll das erkannt werden und je nach dem wie es umbenannt wurde eine Anweisung folgen.
    Die Idee dahinter ist die, dass bestimmte Zeichen nicht erlaubt werden sollen. Nun dachte ich daran, dass mit AutoIt zu realisieren.

    Daraufhin habe ich mit dem Tool "Process Monitor" (Windows Sysinternals) die Dateisystem Aktivitäten aufgezeichnet um zu schauen, was denn da genau passiert beim umbennen einer Datei. Die Aufzeichnung findet ihr im Dateianhang. Dabei habe ich die Datei "abc.txt" welche sich auf D:\ befindet, in "xyz.txt" umbenannt. Den Aufzeichnungen zufolge wurde (unteranderem) eine Operation namens "SetRenameInformationFile" vom Prozess "Explorer.exe" ausgeführt. Meine Idee ist jetzt diese Operationen mit einem AutoIt Script abzuhören, und den Script daraufhin reagieren lassen. Ich habe zwar gegoogelt, aber ich finde keine Hilfe dazu wie ich diese Operationen quasi abhören kann.

    Bin für jede Hilfe sehr dankbar!

    Gruss,
    b4tcher

  • Du könntest die API Funktionen hooken, das würd ich aber niemals mit AutoIt machen...
    Viel einfacher geht's mit ReadDirectoryChangesW. Schau dir dazu einfach mal folgendes Beispiel an:

    Spoiler anzeigen
    [autoit]

    #cs ----------------------------------------------------------------------------

    [/autoit] [autoit][/autoit] [autoit]

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

    [/autoit] [autoit][/autoit] [autoit]

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

    [/autoit] [autoit][/autoit] [autoit]

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

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

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

    [/autoit] [autoit][/autoit] [autoit]

    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)

    [/autoit] [autoit][/autoit] [autoit]

    $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)

    [/autoit] [autoit][/autoit] [autoit]

    _Main()

    [/autoit] [autoit][/autoit] [autoit]

    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

    [/autoit] [autoit][/autoit] [autoit]

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

    [/autoit] [autoit][/autoit] [autoit]

    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

    [/autoit] [autoit][/autoit] [autoit]

    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

    [/autoit] [autoit][/autoit] [autoit]

    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

    [/autoit] [autoit][/autoit] [autoit]

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

    [/autoit] [autoit][/autoit] [autoit]

    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

    [/autoit] [autoit][/autoit] [autoit]

    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

    [/autoit] [autoit][/autoit] [autoit]

    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

    [/autoit] [autoit][/autoit] [autoit]

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

    [/autoit] [autoit][/autoit] [autoit]

    Func _OnEvent_Close ()
    Exit
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    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

    [/autoit] [autoit][/autoit] [autoit]

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

    [/autoit] [autoit][/autoit] [autoit]

    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,$FILE_NOTIFY_CHANGE_SECURITY), _
    "uint", 0, _
    "uint", $pOverlapped, _
    "uint", 0)
    If $aResult[0] = 0 Then
    ConsoleWrite("!> ReadDirectoryChangesW Error(" & @error & "): " & _WinAPI_GetLastErrorMessage() & @LF)
    Exit
    EndIf
    Return $aResult[0]
    EndFunc

    [/autoit]

    mfg K4z

  • Hallo K4z

    Das sieht sehr interessant aus.
    Vielen Dank für deine Hilfe :)

    Gruss, b4tcher

    Einmal editiert, zuletzt von b4tcher (7. Juni 2012 um 12:23)