Verzeichnis überwachen

  • Hallo zusammen,

    ich möchte ein Verzeichnis überwachen und jedesmal wenn eine neue Datei in dem Verzeichnis abgelegt wird, diese bearbeiten und dann in ein anderes Verzeichnis verschieben.

    Das Programm müßte also ständig laufen und immer das Verzeichnis überwachen.

    Wie würdet Ihr da vorgehen? Einfach eine Endlosschleife in der die Bearbeitung läuft? Gibt es da irgendetwas zu beachten bzgl. der Speicherauslastung?

    Wäre toll, wenn Ihr mir da mal ein paar Tipps geben könntet.


    Gruß,
    Timo

  • Hallo Timo,

    ich würde das Grundgerüst in dieser Art aufbauen:

    Spoiler anzeigen
    [autoit]

    #include <File.au3>
    #include <array.au3>

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

    HotKeySet("{Esc}", "_CloseIt") ;mit ESC kann Skript verlassen werden

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

    Opt("GuiOnEventMode", 1)

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

    Global $aFiles, $sPath = "C:\Programme\AutoIt3\testWatch"

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

    AdlibRegister("_searchFiles", 1000) ;alle 1000 ms _searchFiles aufrufen eventuell anpassen

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

    While 1
    Sleep(100000)
    WEnd

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

    Func _searchFiles()
    AdlibUnRegister("_searchFiles") ;_searchFiles deregistrieren
    $aFiles = _FileListToArray($sPath, "*", 1) ;alle File im Pfad in ein Array einlesen
    If IsArray($aFiles) Then ;wenn Array
    For $i = 1 To $aFiles[0] ;Schleifenbegin für alle Files im Array
    ConsoleWrite($aFiles[$i] & @CRLF);Consoleasgabe des Filenamens (kann auskommentiert werden)
    FileDelete($sPath & "\" & $aFiles[$i]) ;<============= mit echter Aktion ersetzen
    Next
    EndIf
    AdlibRegister("_searchFiles", 1000) ;_searchFiles wieder registrieren
    EndFunc ;==>_searchFiles

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

    Func _CloseIt()
    Exit
    EndFunc

    [/autoit]

    mfg (Auto)Bert

    Einmal editiert, zuletzt von AutoBert (17. März 2010 um 23:49)

  • Hallo (Auto)Bert,

    danke für Deine Idee.

    Muß ich mir erstmal genauer anschauen. AdlibRegister sagt mir z.Zt. gar nichts. Werde ma Dein Grundgerüst einbauen.

    Hatte eigentlich geplant das ganze mit "FileFindFirstFile" zu starten und dann das File per "_FileReadToArray" in ein Array einzulesen.

  • Hallo Timo,

    es geht auch ohne Adlib:

    Spoiler anzeigen
    [autoit]

    #include <File.au3>
    #include <array.au3>

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

    HotKeySet("{Esc}", "_CloseIt") ;mit ESC kann Skript verlassen werden

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

    Global $aFiles, $sPath = "C:\Programme\AutoIt3\testWatch"

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

    While 1
    _searchFiles()
    Sleep(1000)
    WEnd

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

    Func _searchFiles()
    $aFiles = _FileListToArray($sPath, "*", 1) ;alle File im Pfad in ein Array einlesen
    If IsArray($aFiles) Then ;wenn Array
    _ArrayDisplay($aFiles,"Dateien in " & $sPath) ;anzeigen der Files des überwahcten Pfades (kann auskommentiert werden)
    For $i = 1 To $aFiles[0] ;Schleifenbegin für alle Files im Array
    ConsoleWrite($aFiles[$i] & @CRLF) ;Consoleasgabe des Filenamens (kann auskommentiert werden)
    FileDelete($sPath & "\" & $aFiles[$i]) ;<============= mit echter Aktion ersetzen
    Next
    EndIf
    EndFunc ;==>_searchFiles

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

    Func _CloseIt()
    Exit
    EndFunc

    [/autoit]

    mfg (Ato)Bert

    Einmal editiert, zuletzt von AutoBert (18. März 2010 um 00:09)

  • Hallo Timo.

    Zu beachten gibt es eigentlich nur dass du deinem Prozessor immer wieder mit sleep ne pause gönnst wenn du gerade nichts brauchst.
    Da du in bestimmten zeitabständen immer wieder etwas ausführen willst bietet sich AdlibRegister (in älteren versionen Adlibenable) an.
    Damit kannst du nämlich eine funktion alle x- Millisekunden ausführen.

    Du kannst aber auch die Endlosschleife wenn dir das lieber ist.
    Aber auch wieder nicht vergessen. Wenn du deinen Prozessor nicht brauchst dann lass ihn schlafen ^^

    Gruß
    Schnitzel

  • Ich habe ein ähnliches Problem gehabt und daher noch folgendes Beispiel liegen gehabt:

    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]

    Zur Nutzung dieses Forum's, ist ein Übersetzer für folgende Begriffe unerlässlich:

    "On-Bort, weier, verscheiden, schädliges, Butten steyling, näckstet, Parr, Porblem, scripe, Kompletenz, harken, manuel zu extramieren, geckukt, würglich, excell, acces oder Compilevorgeng"