Announcement

Collapse
No announcement yet.

Bei Änderungen im Filesystem erfahren, welche Datei neu ist...

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Bei Änderungen im Filesystem erfahren, welche Datei neu ist...

    hallo,

    über die win-api funktionen:
    -FindFirstChangeNotification
    -WaitForSingleObject
    -FindNextChangeNotification

    kann man u. a. ermitteln, ob es änderungen an dateien in einem verzeichnis gegeben hat. wie aber kann ich ermitteln, an welcher datei es diese änderungen gab?

    mfg
    ake

  • #2
    Hallo,

    für diese Aufgabe habe ich nur ein Beispiel für <i>Delphi.NET</i> (Preview, ohne VCL.NET) am Lager:
    <pre>
    <b>unit</b> OssiSoft.DelphiNET.FileSystemWatcherFrm;

    <b>interface</b>

    <b>uses</b>
    System.Windows.Forms,
    System.ComponentModel,
    System.Drawing,
    System.IO,
    Borland.Delphi.SysUtils;

    <b>type</b>
    TFormMain = <b>class</b>(Form)
    <b>private</b>
    FComponents : System.ComponentModel.Container;
    FListBox : ListBox;
    FButton1 : Button;
    FButton2 : Button;
    FStatusBar : StatusBar;
    FFSWatcher : FileSystemWatcher;
    <b>public</b>
    <b>constructor</b> Create;
    <b>procedure</b> InitializeComponent;
    <b>procedure</b> Button1_Click(Sender: TObject; E: EventArgs);
    <b>procedure</b> Button2_Click(Sender: TObject; E: EventArgs);
    <b>procedure</b> aFSW_Created(Sender: TObject; E: FileSystemEventArgs);
    <b>procedure</b> aFSW_Changed(Sender: TObject; E: FileSystemEventArgs);
    <b>procedure</b> aFSW_Deleted(Sender: TObject; E: FileSystemEventArgs);
    <b>procedure</b> aFSW_Renamed(Sender: TObject; E: RenamedEventArgs);
    <b>end</b>;

    <b>var</b>
    FormMain : TFormMain;

    <b>implementation</b>

    <font color="#003399"><i>{ TFormMain }</i></font>

    <b>constructor</b> TFormMain.Create;
    <b>begin</b>
    <b>inherited</b> Create;
    InitializeComponent();
    <font color="#003399"><i>// Instanz der FileSystemWatcher-Klasse vorbereiten</i></font>
    FFSWatcher := FileSystemWatcher.Create;
    FFSWatcher.Created := FileSystemEventHandler.Create(Self, NativeInt(@TFormMain.aFSW_Created));
    FFSWatcher.Changed := FileSystemEventHandler.Create(Self, NativeInt(@TFormMain.aFSW_Changed));
    FFSWatcher.Deleted := FileSystemEventHandler.Create(Self, NativeInt(@TFormMain.aFSW_Deleted));
    FFSWatcher.Renamed := RenamedEventHandler.Create(Self, NativeInt(@TFormMain.aFSW_Renamed));
    <b>end</b>;

    <b>procedure</b> TFormMain.InitializeComponent;
    <b>const</b>
    cHeight = 250;
    cWidth = 350;
    <b>var</b>
    aCtrlArray : <b>array</b>[0..3] <b>of</b> Control;
    aAS : AnchorStyles;
    <b>begin</b>
    FComponents := System.ComponentModel.Container.Create;
    Text := <font color="#9933CC">'FileSystemWatcher'</font>;
    ClientSize := Size.Create(cWidth, cHeight);
    aAS := AnchorStyles(Integer(AnchorStyles.Left) <b>or</b> Integer(AnchorStyles.Bottom));
    FListBox := ListBox.Create;
    <b>with</b> FListBox <b>do</b>
    <b>begin</b>
    Location := Point.Create(8, 8);
    Size := Size.Create(cWidth - 16, cHeight - 75);
    <b>end</b>;
    FButton1 := Button.Create;
    <b>with</b> FButton1 <b>do</b>
    <b>begin</b>
    Anchor := aAS;
    add_click(Button1_Click);
    Location := Point.Create(10, cHeight - 50);
    TabIndex := 1;
    Text := <font color="#9933CC">'&amp;Ein'</font>;
    <b>end</b>;
    AcceptButton := FButton1 <b>as</b> IButtonControl;
    FButton2 := Button.Create;
    <b>with</b> FButton2 <b>do</b>
    <b>begin</b>
    Anchor := aAS;
    add_click(Button2_Click);
    Location := Point.Create(90, cHeight - 50);
    TabIndex := 2;
    Text := <font color="#9933CC">'&amp;Aus'</font>;
    <b>end</b>;
    FStatusBar := StatusBar.Create;
    <b>with</b> FStatusBar <b>do</b>
    <b>begin</b>
    BackColor := SystemColors.Control;
    Location := Point.Create(0, cHeight - 20);
    TabIndex := 3;
    Text := <font color="#9933CC">'(Fertig)'</font>;
    <b>end</b>;
    aCtrlArray[0] := FListBox;
    aCtrlArray[1] := FButton1;
    aCtrlArray[2] := FButton2;
    aCtrlArray[3] := FStatusBar;
    Controls.AddRange(aCtrlArray);
    <b>end</b>;

    <b>procedure</b> TFormMain.Button1_Click(Sender: TObject; E: EventArgs);
    <b>begin</b>
    FFSWatcher.Path := <font color="#9933CC">'C:\Temp'</font>;
    FFSWatcher.Filter := <font color="#9933CC">'*.txt'</font>;
    FFSWatcher.IncludeSubdirectories := True;
    FFSWatcher.EnableRaisingEvents := True;
    FStatusBar.Text := <font color="#9933CC">'Verzeichnis C:\Temp wird überwacht'</font>;
    <b>end</b>;

    <b>procedure</b> TFormMain.Button2_Click(Sender: TObject; E: EventArgs);
    <b>begin</b>
    FFSWatcher.EnableRaisingEvents := False;
    FStatusBar.Text := <font color="#9933CC">''</font>;
    <b>end</b>;

    <b>procedure</b> TFormMain.aFSW_Renamed(Sender: TObject; E: RenamedEventArgs);
    <b>begin</b>
    FListBox.Items.Add(Format(<font color="#9933CC">'Datei %s wurde nach %s umbenannt.'</font>,
    [e.OldName, e.Name]));
    <b>end</b>;

    <b>procedure</b> TFormMain.aFSW_Created(Sender: TObject; E: FileSystemEventArgs);
    <b>begin</b>
    FListBox.Items.Add(Format(<font color="#9933CC">'Neue Datei: %s'</font>, [e.Name]));
    <b>end</b>;

    <b>procedure</b> TFormMain.aFSW_Changed(Sender: TObject; E: FileSystemEventArgs);
    <b>begin</b>
    FListBox.Items.Add(Format(<font color="#9933CC">'Geänderte Datei: %s'</font>, [e.Name]));
    <b>end</b>;

    <b>procedure</b> TFormMain.aFSW_Deleted(Sender: TObject; E: FileSystemEventArgs);
    <b>begin</b>
    FListBox.Items.Add(Format(<font color="#9933CC">'Gelöschte Datei: %s'</font>, [e.Name]));
    <b>end</b>;

    <b>end</b>.
    </pre>
    Im .NET-Framework gibt es die Komponente <b>FileSystemWatcher</b>, die alle Benachrichtigungen über Ereignisse an den Client weiterreicht und dabei auch den Dateinamen übergibt. Mit dem "alten" Delphi muss man die WMI-Events selbst aktivieren/abfragen

    Comment


    • #3
      hallo,

      richtig, die kompo sendet das event und eine klasse welche die namen etc . der datei enthält die das event ausgelöst hat. meine klasse sendet auch das event, aber eben nicht die datei, und muß wissen welche datei geändert wurde.

      weißt du vielleicht, wie man von dem handle einer datei auf deren namen kommen kann???

      mfg
      ak

      Comment


      • #4
        hallo ake, probier das mal:
        <pre>unit Unit2;

        interface

        uses
        Classes,windows,dialogs;

        type
        TWatch = class(TThread)
        private
        changehandle:THandle;
        watchpath : String;
        { Private-Deklarationen }
        protected
        procedure Execute; override;
        procedure RefreshListbox;
        destructor Destroy;
        public
        constructor Create(path : String);
        end;

        implementation
        uses unit1;

        constructor TWatch.Create(path : String);
        begin
        inherited Create(False);
        watchpath:= path;
        FreeOnTerminate := True;
        end;

        procedure TWatch.Execute;
        begin
        changehandle:=FindFirstChangeNotification(PChar(wa tchpath),FALSE,FILE_NOTIFY_CHANGE_FILE_NAME);
        if changehandle <> INVALID_HANDLE_VALUE then begin
        while True do begin // normalerweise eine Endlosschleife
        if WaitForSingleObject(changehandle,500)= WAIT_OBJECT_0 then begin
        synchronize(RefreshListbox);
        end;
        FindNextChangeNotification(changehandle);
        if Terminated then break;
        end;
        end;
        end;

        procedure TWatch.RefreshListbox;
        begin
        form1.filelistbox1.update;
        end;

        destructor TWatch.Destroy;
        begin
        if changehandle<> NULL then FindCloseChangeNotification(changehandle);
        inherited Destroy;
        end;

        end.
        </pre&gt

        Comment


        • #5
          hallo,

          @Raik Cebulla: genau an dieser stelle bin ich, ich weiß also das sich etwas geändert hat, aber nun möchte ich auch wissen, an welcher datei (name, das handle hab ich ja durch changehandle, aber eben keinen namen) sich was geändert hat.
          ich brauch also was, das anhand des handles der datei feststellen kann wie diese datei heißt!

          vielen dank für eure bisherige antworten. wenn jemand noch was einfällt ruhig posten. danke.

          mfg
          ak

          Comment


          • #6
            hallo nochmal,

            @andreas kosch: der FFSWatcher ist doch eine klasse von dotnet. die muß doch momentan zumindest intern auch noch auf die api zugreifen, kann man anhand des quellcodes der Watcher-klasse nicht nachschauen wie die den dateinamen als argument mitgegben können? oder gibt es von windowsforms keinen quellcode wie z. b. bei vcl? das wäre ja schwach...

            mfg
            ak

            Comment


            • #7
              hallo ake.

              es gibt bei FindFirstChangeNotification aber auch noch andere attribute:

              zB file _notify_change_size erkennt die änderung der dateigröß

              Comment


              • #8
                hallo,

                ja schon, aber ich möchte wissen wie die datei heißt in der die attribute bzw. der name oder sonst was geändert wird. ich will nicht nur wissen, das etwas geändert wird, sondern wie die datei konkret heißt, z. b. Testdatei2.txt oder sonst wie...

                mfg
                ak

                Comment


                • #9
                  Hallo, <br>
                  <br>
                  es gibt die Möglichkeit ein ICopyHook Interface in einem COM Object zu implementieren. Die Shell ruft dann deine Methode auf und gibt die entsprechenden Parameter mit, u.a. den Dateinamen. Über diese Shellextention kann man auch unterverzeichnisse überwachen lassen und auf andere ereignisse wie nur das hizukommen von Dateien reagieren. In der Delphi Windows SDK Hilfe findet man etwas dazu, wenn das nicht reicht, kann ich dir auch ein Beispiel mailen.<br>
                  <br>
                  mfg
                  <br>Simon Rot

                  Comment


                  • #10
                    @ Simon (Posting 8):

                    Kannst Du mir ein kleines Beispiel mailen bzw. hier im Forum posten?

                    Grüsse,
                    Carste

                    Comment


                    • #11
                      @Carsten Schmitz: das Beispiel ist etwas zu umfangreich um es zu posten. Aber wenn Du mir deine mail Adresse gibst kann ich dir ein Beispiel mailen.<br>
                      mfg Simon Rot

                      Comment


                      • #12
                        @ Simon (Posting 10):
                        Gerne nehme ich Dein Angebot an. Schick es mir doch bitte zu [email protected]

                        Grüsse,
                        Carsten

                        P.S.: Funktioniert Dein Beispielcode auch mit Delphi 5

                        Comment


                        • #13
                          @Caersten: Ehrlich gesagt, habe ich diesen Code nur mit Delphi 5 verwendet, von daher müsste es funktionieren.<br>
                          Falls sonst noch jemand interesse hat, soll er seine Mail Adresse posten und ich maile es.<br>
                          mfg<br>
                          Simon Rot

                          Comment


                          • #14
                            Ich hätte interesse :-)


                            Dank
                            Zuletzt editiert von Bernhard Geyer; 18.03.2009, 10:16. Reason: Mail-Adresse gelöscht.

                            Comment


                            • #15
                              Hallo,

                              siehe auch Beitrag
                              <a href="http://www.entwickler-forum.de/webx?50@@.ee8a353">Erkennen, wenn Dateien in ein Verzeichnis kopiert werden</a>

                              Gruß Thorbe

                              Comment

                              Working...
                              X