Datei "session.txt" (in einem fest definierten Verzeichnis) überwachen und Folgeaktion auslösen

  • Hallo!

    In einem fest definierten Verzeichnis wird durch ein anderes Programm automatisch eine Datei "session.txt" generiert und auch automatisch wieder gelöscht.
    Diese Datei "session.txt" beinhaltet 1 Zeile.

    Ich möchte gerne den Inhalt dieser 1 Zeile auslesen (FileRead-Befehl ist mir bekannt) und den Inhalt in eine weitere, fest definierte Zieldatei (z.B. "C:\Logs\sessions.txt") wegschreiben (darin ans Ende). Der FileWrite-Befehl ist mir ebenfalls geläufig.

    Wichtig ist, dass mein Skript permanent läuft, denn es muss ja ständig überwachen, ob die auszulesende Quelldatei "session.txt" in dem von mir fest vorgegebenen Verzeichnis existiert oder nicht.

    Wichtig ist auch, dass das Auslesen des Inhalts der Quelldatei "session.txt" und das Hineinschreiben dieses Inhalts in die Zieldatei "C:\Logs\sessions.txt" nur 1 einziges mal stattfinden soll! Heißt konkret: Wenn der Inhalt geschrieben wurde, darf derselbe Inhalt nicht noch ein weiteres mal geschrieben werden, solange bis die Quelldatei "session.txt" wieder gelöscht wurde.


    Mein Skript muss - so nehme ich es an - also auch prüfen, ob meine Quelldatei "session.txt" gelöscht wurde.


    Kann mir jemand diesbezüglich helfen?
    Vielen Dank im Voraus!

  • Zitat

    Ich würde _WinAPI_ShellChangeNotifyRegister benutzen.

    Und ich würde dazu gerne die AutoIt-Umsetzung sehen 8o

    Habe vor längerer Zeit selbst vor dem Problem gestanden und einfach alle 3-4 Sekunden evtl. Änderungen an der Datei per

    [autoit]

    FileGetTime()

    [/autoit]

    ausgelesen.
    Da das aber (warum auch immer) bei einigen auf div. Servern liegenden Dateien nicht 100%ig funktioniert hat, habe ich die einfachste Methode genommen und den Dateiinhalt abgefragt.

    [autoit]

    If $Datei_Inhalt_alt <> $Datei_Inhalt_neu then ;Dateiinhalt hat sich geändert
    $Datei_Inhalt_alt = $Datei_Inhalt_neu
    ...blablub
    endif

    [/autoit]

    Bei hunderten MB großen Dateien macht das übers Netz keinen schlanken Fuß!
    Bei sehr kleinen Dateien, die sich häufig ändern (wie in meinem Fall), ist das eine todsichere Methode.

  • Und ich würde dazu gerne die AutoIt-Umsetzung sehen

    _WinAPI_ShellChangeNotifyRegister - Beispiel
    [autoit]

    #RequireAdmin
    #include <APIShellExConstants.au3>
    #include <GUIConstantsEx.au3>
    #include <WinAPI.au3>
    #include <WinAPIShellEx.au3>

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

    HotKeySet("q", raus) ; mit "q" Programm beenden

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

    Global Const $s_PATH = FileGetLongName("D:\Temp")

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

    #Region ShellEvent registrieren
    Global $h_GUI = GUICreate("")
    Global $h_Msg = _WinAPI_RegisterWindowMessage('irgendwas') ; Die Message "irgendwas" wird an das Fenster $h_GUI gesendet wenn ein Event auftritt
    GUIRegisterMsg($h_Msg, 'ReactOnEvents')

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

    Global $h_ShellNotify1 = _WinAPI_ShellChangeNotifyRegister($h_GUI, $h_Msg, $SHCNE_ALLEVENTS, 0x3, $s_PATH)
    #EndRegion ShellEvent registrieren

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

    Do
    Sleep(100)
    Until 0

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

    ; Funktion die aufgerufen wird wenn ein Event auftritt:
    Func ReactOnEvents(Const $hWndGUI, Const $MsgID, Const $wParam, Const $lParam)
    Local $s_PATH = DllCall("Shell32.dll", "BOOLEAN", "SHGetPathFromIDListW", "ptr", DllStructCreate("PTR A; PTR", $wParam).A, "wstr", "")[2]

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

    ConsoleWrite(StringFormat("% 20s\t%s\n", GetSHCNEConstNameByValue($lParam), $s_PATH))
    EndFunc ;==>ReactOnEvents

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

    ; Ermittelt aus dem Wert der SHCNE-Konstanten den Konstantennamen
    Func GetSHCNEConstNameByValue($value)
    Local Static $a_Consts[][2] = [["ALLEVENTS", 0x7FFFFFFF], ["ASSOCCHANGED", 0x8000000], ["ATTRIBUTES", 0x00000800], ["CREATE", 0x00000002], ["DELETE", 0x00000004], ["DRIVEADD", 0x00000100], ["DRIVEADDGUI", 0x00010000], ["DRIVEREMOVED", 0x00000080], ["EXTENDED_EVENT", 0x04000000], ["FREESPACE", 0x00040000], ["MEDIAINSERTED", 0x00000020], ["MEDIAREMOVED", 0x00000040], ["MKDIR", 0x00000008], ["NETSHARE", 0x00000200], ["NETUNSHARE", 0x00000400], ["RENAMEFOLDER", 0x00020000], ["RENAMEITEM", 0x00000001], ["RMDIR", 0x00000010], ["SERVERDISCONNECT", 0x00004000], ["UPDATEDIR", 0x00001000], ["UPDATEIMAGE", 0x00008000], ["UPDATEITEM", 0x00002000], ["DISKEVENTS", 0x0002381F], ["GLOBALEVENTS", 0x0C0581E0], ["INTERRUPT", 0x80000000]]
    For $i = 0 To UBound($a_Consts) - 1
    If $value = $a_Consts[$i][1] Then Return $a_Consts[$i][0]
    Next
    Return ""
    EndFunc

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

    Func raus()
    #forceref $h_ShellNotify1
    _WinAPI_ShellChangeNotifyDeregister($h_ShellNotify1)
    Exit
    EndFunc ;==>raus

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

    In dem Beispiel werden alle Events in einem Verzeichnis (nicht rekursiv) getrackt.
    Teste es mal - bei mir funktioniert es.

    Da das aber (warum auch immer) bei einigen auf div. Servern liegenden Dateien nicht 100%ig funktioniert hat,

    Hier könnte es durchaus Probleme geben. Ich zitiere mal MSDN:

    Zitat

    Registers a window to receive notifications from the file system or Shell, if the file system supports notifications.


    Oscar
    Danke für den Hinweis mit der fertigen UDF. Hab das bisher immer manuell gemacht - so wird es deutlich übersichtlicher.

  • AspirinJunkie,
    Danke!
    Funktioniert einwandfrei, mal schauen wie ich das (wenn es auch remote funktioniert) in VBA umsetze :thumbup:

  • Funktioniert einwandfrei, mal schauen wie ich das (wenn es auch remote funktioniert) in VBA umsetze


    Als erstes: Mein Beileid für den Zwang zu VB...
    Als zweites: Wenn du das umsetzen musst, hast du sicherlich nicht die AutoIt-API-Funktion zur Verfügung.
    Ich hatte das Ganze schon mal ohne die _WinAPI-Funktion direkt mit den nativen DLL-Funktionen gemacht - das wäre als Grundlage für die Überführung wohl besser geeignet: >>Klickmich<<

  • Zitat

    Als erstes: Mein Beileid für den Zwang zu VB...

    8) wat mutt, dat mutt!
    Problem ist einfach, dass ich einwandfrei und vor allem SICHER funktionierende Programme abliefern muss. Und dass keine Mitarbeiter mit wirklicher Programmiererfahrung zur Verfügung stehen. Es macht keinen Sinn, irgendwelche "Experimente" zu veranstalten, und 100 Mitarbeiter haben plötzlich echten Stress, weil div. Programme nicht funktionieren, von Produktionseinschränkungen bzw. -Ausfällen ganz zu schweigen...
    Dazu erstelle ich die Software "nebenbei", habe ja noch einen "richtige" Aufgabe :rolleyes: ,da sollte man darauf achten, dass sich der "Support" gegen Null orientiert.
    Und wenn dann irgendwer komplette Verzeichnis(inhalte)se verschiebt, dann müssen die Daten trotzdem noch gefunden werden und die Programme sollten funktionieren :rock:
    So etwas prägt 8o