AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren

ReadDirectoryChangesW

Ein Thema von Cylence · begonnen am 14. Mär 2008 · letzter Beitrag vom 15. Nov 2015
Antwort Antwort
Seite 1 von 2  1 2   
Benutzerbild von Cylence
Cylence

Registriert seit: 2. Sep 2004
Ort: Allgäu
246 Beiträge
 
Delphi 7 Enterprise
 
#1

ReadDirectoryChangesW

  Alt 14. Mär 2008, 19:06
Hi,

ich möchte in einen MediaPlayer eine Möglichkeit einbauen das dieser eins oder wenn möglich mehrere Ordner automatisch überwacht und in liste hinzufügt oder entfernt was halt grad passiert...

Dazu hab ich 2 ansätze gefunden aber der erste geht einmal und das wars und der zweite geht garnich

kennt sich einer von euch da aus?

Delphi-Quellcode:

type
  FileNotifyInformation = Record
                             NextEntryOffset : DWORD;
                             Action : DWORD;
                             FileNameLength : DWORD;
                             FileName : Array[0..MAX_PATH] Of WCHAR;
                         end;
PFileNotifyInformation = ^FileNotifyInformation;

//---------------------------------------------------Version 1------------

procedure TcsDirThread.Execute;
var
  pBuf : Pointer;
  dwBufLen : DWORD;
  dwRead : DWORD;
  FNI : FileNotifyInformation;
  pWork : Pointer;
  sFileName : Widestring;
  dwWaitStatus : DWORD;
  FhFile : THandle;
  hNotifity : Cardinal;
  FsFileName : String;
  ReNode : TTreeNode;
  tempX : String;
  i : Integer;
begin

  Form1.Memo1.Lines.Add('Überwachung gestartet');
  FhFile := CreateFile(PChar(Form1.FolderToWatch1), GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_ATTRIBUTE_DIRECTORY or FILE_FLAG_BACKUP_SEMANTICS, 0);
  Priority := tpLower;
                         
  hNotifity := FindFirstChangeNotification(PChar(Form1.FolderToWatch1), //Verzeichnis
                                           True, //unterverzeichnisse überwachen
                                           FILE_NOTIFY_CHANGE_FILE_NAME or
                                           FILE_NOTIFY_CHANGE_LAST_WRITE or
                                           FILE_NOTIFY_CHANGE_SIZE or
                                           FILE_ACTION_ADDED or
                                           FILE_ACTION_REMOVED or
                                           FILE_ACTION_MODIFIED);
  if (FhFile = INVALID_HANDLE_VALUE) or (FhFile = 0) then
  begin
    RaiseLastWin32Error;
    Terminate;
  end;
  if (hNotifity = INVALID_HANDLE_VALUE) then
  begin
    RaiseLastWin32Error;
    Terminate;
  end;

  dwBufLen := 65536;
  pBuf := AllocMem(dwBufLen);
  try
    while ((FindNextChangeNotification(hNotifity)) and (not terminated)) do
    begin
      Synchronize(Application.ProcessMessages);
      dwWaitStatus := WaitForSingleObject(hNotifity, 1000);
      if (dwWaitStatus = WAIT_FAILED) then
      begin
        RaiseLastWin32Error;
        Terminate;
      end;
      if (dwWaitStatus = WAIT_OBJECT_0) then
      begin
        ReadDirectoryChangesW(FhFile,pBuf,dwBufLen,true,
                              FILE_NOTIFY_CHANGE_FILE_NAME or
                              FILE_NOTIFY_CHANGE_DIR_NAME or
                              FILE_NOTIFY_CHANGE_ATTRIBUTES or
                              FILE_NOTIFY_CHANGE_SIZE or
                              FILE_NOTIFY_CHANGE_LAST_WRITE or
                              FILE_NOTIFY_CHANGE_CREATION or
                              FILE_ACTION_ADDED or
                              FILE_ACTION_REMOVED or
                              FILE_ACTION_MODIFIED,
                              @dwRead,nil,nil);
        pWork := pBuf;
        repeat
          StrMove(@FNI,pWork,12);
          PChar(pWork) := PChar(pWork)+12;
          sFileName := StringOfChar(#00,FNI.FileNameLength);
          StrMove(@sFileName[1],pWork,FNI.FileNameLength);
          FsFileName := WideCharToString(PWideChar(sFileName));
          FsFileName := copy(FsFileName,1,length(FsFileName) shl 1);

          //Synchronize(AddFileToList);

          PChar(pWork) := PChar(pBuf)+FNI.NextEntryOffset;
           if FNI.Action = FILE_ACTION_ADDED then begin
              Form1.Memo1.Lines.Add('+ ' + FsFileName);
           end;
           if FNI.Action = FILE_ACTION_REMOVED then begin
              Form1.Memo1.Lines.Add('- ' + FsFileName);
           end;
         { FILE_NOTIFY_CHANGE_FILE_NAME or
          FILE_NOTIFY_CHANGE_DIR_NAME or
          FILE_NOTIFY_CHANGE_ATTRIBUTES or
          FILE_NOTIFY_CHANGE_SIZE or
          FILE_NOTIFY_CHANGE_LAST_WRITE or
          FILE_NOTIFY_CHANGE_LAST_ACCESS or
          FILE_NOTIFY_CHANGE_CREATION {or
          FILE_NOTIFY_CHANGE_SECURITY}


          //break;

        until FNI.NextEntryOffset = 0;
      end;
    end;

   { if (LowerCase(ExtractFileExt(FsFileName)) = '.bmp') then
    begin
      PostMessage(MainForm.Handle, Verzeichnisaenderung_bmp, 0, ProjektID);
    end; }


  finally
    FreeMem(pBuf,dwBufLen);
  end;
end;

//------------------------------------------------------Version2--------------------------

procedure TMonitorThread.Execute;
var
  pBuf: Pointer;
  dwBufLen: DWORD;
  dwRead: DWORD;
  FNI: FileNotifyInformation;
  pWork: Pointer;
  sFileName: Widestring;
  FsFileName : String;
  i : Integer;
  temp : string;
  ReNode : TTreeNode;
  DirectoryHandle : THandle;
begin
  DirectoryHandle := CreateFile( PCHar(Form1.FolderToWatch2), GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_ATTRIBUTE_DIRECTORY or FILE_FLAG_BACKUP_SEMANTICS, 0);
  Priority := tpLower;
  Form1.Memo2.Lines.Add('Überwachung gestartet');
  dwBufLen := 65536;
  pBuf := AllocMem(dwBufLen);
  while not terminated do
  begin
    ReadDirectoryChangesW(DirectoryHandle, pBuf, dwBufLen, True,
                          FILE_NOTIFY_CHANGE_LAST_WRITE,
                          @dwRead, nil, nil);
    pWork := pBuf;
    repeat
      StrMove(@FNI,pWork,12);
      PChar(pWork) := PChar(pWork)+12;
      sFileName := StringOfChar(#00,FNI.FileNameLength);
      StrMove(@sFileName[1],pWork,FNI.FileNameLength);
      FsFileName := WideCharToString(PWideChar(sFileName));
      FsFileName := copy(FsFileName,1,length(FsFileName) shl 1);
      PChar(pWork) := PChar(pBuf)+FNI.NextEntryOffset;
           if FNI.Action = FILE_ACTION_ADDED then begin
              Form1.Memo2.Lines.Add('+ ' + FsFileName);
           end;
           if FNI.Action = FILE_ACTION_REMOVED then begin
              Form1.Memo2.Lines.Add('- ' + FsFileName);
           end;
         { FILE_NOTIFY_CHANGE_FILE_NAME or
          FILE_NOTIFY_CHANGE_DIR_NAME or
          FILE_NOTIFY_CHANGE_ATTRIBUTES or
          FILE_NOTIFY_CHANGE_SIZE or
          FILE_NOTIFY_CHANGE_LAST_WRITE or
          FILE_NOTIFY_CHANGE_LAST_ACCESS or
          FILE_NOTIFY_CHANGE_CREATION {or
          FILE_NOTIFY_CHANGE_SECURITY}


          //break;
          
    until FNI.NextEntryOffset = 0;
  end;
  FreeMem(pBuf,dwBufLen);
end;

//-------------------------------------------------------------------------------------------------------------------------------------v
was mach ich falsch und mach ich was falsch?

Thanx

Tom
Tom
Just DO it
  Mit Zitat antworten Zitat
ManfredG

Registriert seit: 12. Feb 2007
Ort: Berlin
34 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#2

Re: ReadDirectoryChangesW

  Alt 15. Mär 2008, 18:26
Hallo Tom,
ich habe heute leider nicht den Nerv deinen Code zu überprüfen, hatte aber in der Vergangenheit schon mal ein ähnliches Problem und deshalb eine Komponente entwickelt. Vielleicht hilft dir das weiter.

Hier die Komponenten:
Delphi-Quellcode:
unit FldrControl;

interface

uses
  Windows, SysUtils, Classes, cThread, SyncObjs;
// dieser Typ steht für die dwFilter-Konstanten von ReadDirectoryChangesW
// er ist erfoderlich, da die Filter-Konstanten nicht direkt verwendet werden können,
// da ihr Wertbereich 128 überschreitet und nicht mehr in einen SET OF passen
type
  opTyp = set of (fncFileName,fncDirName,fncAttributes,fncSize,fncLastWrite,fncLastAccess,fncCreation,fncSecurity);
// die Funktion dient der Datenübergabe an ein übergeordnetes Fenster
Type
  TOnGetData = Procedure(Folder: String; Action: Integer) of Object;
{ Nichtvisuelle Komponente zur Ordnerüberwachung
  Properties:
    Folder - (lesen/schreiben) der Ordner, ab dem die Struktur überwacht werden soll
    ThreadExists - (lesen) TRUE, wenn der Überwachungsthread existiert
    ThreadSuspended - (lesen) TRUE, wenn der Thread suspendiert ist.
    CtrlTyp - (lesen/schreiben) Ersatz für dwFilter-Konstanten im Objektinspektor
    OnGetResult - Datenübergabeereignis
  Funktionen:
    Create, Destroy
    GetData - Verbindungsfunktion für Datenübergabe im Objektinspektor
    StartThread    - Start des Überwachungsthreads
    StopThread    - Beenden des Überwachungsthreads
    SuspendThread  - Suspendieren des Überwachungsthreads
    ResumeThread;  - Wiederaufnehme des Überwachungsthreads
}

type
  TFldrControl = class(TComponent)
  private { Private-Deklarationen }
    ControlThread: CtrlThread; // Zeiger auf das Thread-Objekt
    FOrdnerName : String; // zu überwachender Ordner
    SuspEventName: String; // benamter Event für die Einleitung von Suspend
    TermEventName: String; // benamter Event für die Einleitung von Terminate
    FOnData : TOnGetData;
    ThrdExists : boolean; // Kennzeichen für die Existenz des Threads
    wSelChg : DWORD; // Filter für ReadDirectoryChangesW
    TypSelChg : opTyp; // Alias für Filter (Objektinspektor)
  protected { Protected-Deklarationen }
    procedure SetOrdnerName(NewFolder: String); // ändern Ordnername
    function GetThreadStatus: boolean; // Abfrage Threadstatus
    procedure SetTypSelChg(Value: opTyp); // ändern Filter
  public { Public-Deklarationen }
    EvOrdner : String; // Rückgabedaten Ordnername bei Ereignis
    EvAction : integer; // Rückgabedaten Ereignis
    Constructor Create(AOwner: TComponent); override;
    Destructor Destroy; override;
    Procedure StartThread;
    Procedure StopThread;
    Procedure SuspendThread;
    Procedure ResumeThread;
    procedure GetData;
    function GetReason(const AdwReasonCode: DWORD): String;
  published { Published-Deklarationen }
    Property Folder : String Read FOrdnerName write SetOrdnerName;
    Property ThreadExists : boolean read ThrdExists default TRUE;
    Property ThreadSuspend : boolean read GetThreadStatus;
    Property OnGetResult : TOnGetData read FOnData write FOnData;
    Property CtrlTyp : opTyp read TypSelChg write SetTypSelChg;
  end;

procedure Register;
{*R *.res}
implementation

procedure Register;
begin
  RegisterComponents('Eigene', [TFldrControl]);
end;

Constructor TFldrControl.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  ControlThread:=NIL; // überflüssig
  ThrdExists :=FALSE; // Ausgangssituation
  SetTypSelChg([fncFileName,fncDirName]); // Standartwert für Filter
end;

Destructor TFldrControl.Destroy;
begin
  inherited Destroy;
end;

// Umwandlung opTyp (SET OF) in DWORD für Filterkonstanten
procedure TFldrControl.SetTypSelChg;
var res: DWORD;
begin
  res:=0;
  if fncFileName in Value then res:=res or FILE_NOTIFY_CHANGE_FILE_NAME;
  if fncDirName in Value then res:=res or FILE_NOTIFY_CHANGE_DIR_NAME;
  if fncAttributes in Value then res:=res or FILE_NOTIFY_CHANGE_ATTRIBUTES;
  if fncSize in Value then res:=res or FILE_NOTIFY_CHANGE_SIZE;
  if fncLastWrite in Value then res:=res or FILE_NOTIFY_CHANGE_LAST_WRITE;
  if fncLastAccess in Value then res:=res or FILE_NOTIFY_CHANGE_LAST_ACCESS;
  if fncCreation in Value then res:=res or FILE_NOTIFY_CHANGE_CREATION;
  if fncSecurity in Value then res:=res or FILE_NOTIFY_CHANGE_SECURITY;
  wSelChg:=res;
  TypSelChg:=Value;
  // nach einer Filteränderung muß der Thread eventuell neu gestartet werden!
  if not ThrdExists then Exit; // außer er existiert nicht
  // wenn der Thread suspendiert ist..
  if ControlThread.Suspended then begin
    ControlThread.Resume; // dann aktivieren
    StopThread; // vernichten
    StartThread; // neu starten
  end else begin // wenn er schon läuft
    StopThread; // vernichten
    StartThread; // neu starten
  end;
end;

//
function TFldrControl.GetThreadStatus: boolean;
begin
  if ThrdExists
  then Result:=ControlThread.Suspended
  else Result:=TRUE;
end;

procedure TFldrControl.SetOrdnerName;
begin
  FOrdnerName:=NewFolder;
  if not ThrdExists then Exit;
  if ControlThread.Suspended then begin
    ControlThread.Resume;
    StopThread;
    StartThread;
  end else begin
    StopThread;
    StartThread;
  end;
end;

procedure TFldrControl.GetData;
begin
  if Assigned(OnGetResult)
  then OnGetResult(EvOrdner,EvAction);
end;

Procedure TFldrControl.StartThread;
var SelfName: String;
begin
  if ThrdExists then exit;
  if (Length(FOrdnerName)=0) or (Not DirectoryExists(FOrdnerName)) then begin
    MessageBox(0,'Ordner nicht angegeben','Fehler',MB_OK);
    Exit;
  end;
  if wSelChg=0 then begin
    MessageBox(0,'Überwachungskriterium nicht angegeben','Fehler',MB_OK);
    Exit;
  end;
  ControlThread:=CtrlThread.Create(self,FOrdnerName,wSelChg);
  ThrdExists :=TRUE;
  SelfName :=IntToStr(ControlThread.Handle);
  SuspEventname:=SelfName+'W';
  TermEventName:=SelfName+'N';
  ControlThread.SetEventNames(SuspEventname,TermEventName);
  ControlThread.Resume;
end;

Procedure TFldrControl.StopThread;
var StopEvent: TEvent;
begin
  StopEvent:=TEvent.Create(nil,FALSE,FALSE,TermEventName);
  PulseEvent(StopEvent.Handle);
  StopEvent.Free;
  (**)// am 09.09.2007 zugefügt
      // wenn der Thread nicht durch Terminate vernichtet wird (FreeOnTerminate=TRUE)
      // bleibt er nach Änderung des Ordnernamens auf dem alten Ordner stehen !
  if ThrdExists then ControlThread.Terminate;
  (**)
  ThrdExists:=FALSE;
end;

Procedure TFldrControl.SuspendThread;
var SuspEvent: TEvent;
begin
  SuspEvent:=TEvent.Create(nil,FALSE,FALSE,SuspEventName);
  SuspEvent.SetEvent;
  SuspEvent.ResetEvent;
  SuspEvent.Free;
end;

Procedure TFldrControl.ResumeThread;
begin
  ControlThread.Resume;
end;

// Ereignisgrung in Text umwandeln
function TFldrControl.GetReason(const AdwReasonCode: DWORD): String;
begin
  case AdwReasonCode of
    FILE_ACTION_ADDED : Result := 'hinzugefügt';
    FILE_ACTION_REMOVED : Result := 'gelöscht';
    FILE_ACTION_MODIFIED : Result := 'verändert';
    FILE_ACTION_RENAMED_OLD_NAME : Result := 'umbenannt. Alter Name.';
    FILE_ACTION_RENAMED_NEW_NAME : Result := 'umbenannt. Neuer Name.';
    else Result := 'Ungültiger Reason Code: '+IntToHex(AdwReasonCode,8);
  end;
end;

end.
Zu dieser Komponente gehört noch folgender Thread:

Delphi-Quellcode:
unit cThread;

interface

uses
  SysUtils, Classes, Controls, SyncObjs, Windows, ShellApi, ComCtrls;

const
  FILE_LIST_DIRECTORY = $0001;
  WaitDir = WAIT_OBJECT_0;
  WaitTerm = WAIT_OBJECT_0+1;
  WaitSusp = WAIT_OBJECT_0+2;

type
  CtrlThread = class(TThread)
  private
    FhFile : DWORD; // Handle von CreateFile auf die kontrollierte Ordnerstruktur
    FsDirPath : string; // der Pfad zu der Ordnerstruktur, die zu überwachen ist
    FsFileName : string; // ein Dateiname aus einen Überwachungsereignis der Ordner
    FAction : DWORD; // Verzeichnisaktion, die erfolgte
    FileEvent : THandle; // Handle für das Ordnerüberwachungsereignis
    SuspEvent : TEvent; // Ereignis für das suspendieren des Threads
    SuspEvName : String; // Name dieses Ereignisses
    TermEvent : TEvent; // eigenes Ereignis, das für den Abbruch des Threads erforderlich ist
    TermEvName : String; // Name des Abbruchereignisses
    Owner : TComponent; // Besitzer des Threads
    FFilter : DWord; // Filter für
    procedure SendData; // eine Beispielfunktion für die Datenübergabe
  public
    constructor Create(AOwner: TComponent; const AsDirPath: string; AFilter: DWORD);
    destructor Destroy; override;
    procedure Execute; override;
    Procedure SetEventNames(AwEvName,AnEvName: string);
  end;

  PFILE_NOTIFY_INFORMATION = ^FILE_NOTIFY_INFORMATION; // Strukturzeiger
  FILE_NOTIFY_INFORMATION = packed record // Ereignisrecord für !ein! überwachungsereignis
    dwNextEntryOffset : DWORD; // Offset zum nächsten Eintrag
    dwAction : DWORD; // Ereignisgrund
    dwFileNameLength : DWORD; // Länge des Dateinamens
    dwFileName : WideString; // Dateiname
  end;



implementation
uses FldrControl;

constructor CtrlThread.Create(AOwner: TComponent; const AsDirPath: string; AFilter: DWORD);
begin
  inherited Create(TRUE); // Thread erstellen und nicht laufen lassen
  FsDirPath := AsDirPath; // der zu überwachende Pfad
  Owner := AOwner; // der Besitzer des Threads
  FFIlter := AFilter; // Filter für .. übernehmen
  FreeOnTerminate := true; // Thread nach Beendigung vernichten lassen
end;

// Namen für die Ereignisse:
// werden von der Komponente aus gesetzt, was aber erst geschehen kann,
// wenn der Thread creiert ist
Procedure CtrlThread.SetEventNames(AwEvName,AnEvName: String);
begin
  SuspEvName:=AwEvName;
  TermEvName:=AnEvName;
end;

procedure CtrlThread.Execute;
var
  pBuffer : Pointer; // Puffer für die Rückgabedaten von ReadDirectoryChangesW
  dwBufLen : DWORD; // Größe des Puffers
  dwRead : DWORD; // Anzahl der Daten im Puffer
  PInfo : PFILE_NOTIFY_INFORMATION; // Maske für die Pufferdaten
  dwNextOfs : DWORD; // Position des Folgesatzes im Puffer (bei 0 - keiner)
  dwFnLen : DWORD; // Dateinamenlänge
  Overlap : TOverlapped; // Asynchronstruktur
  WaitResult: DWORD; // Rückgabewert von WaitForMultipleObjects
  EventArray : Array[0..2] of THandle; // Array der Handles für WaitForMultipleObjects
begin
  // Handle auf das zu überwachende Verzeichnis
  FhFile:= CreateFile(PChar(FsDirPath),
                      FILE_LIST_DIRECTORY or GENERIC_READ,
                      FILE_SHARE_READ or FILE_SHARE_WRITE or FILE_SHARE_DELETE,
                      nil,
                      OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS or FILE_FLAG_OVERLAPPED,
                      0);
  if (FhFile = INVALID_HANDLE_VALUE) or (FhFile = 0) then exit;
  // Ereignis für Asynchronbehandlung von ReadDirectoryChangesW
  FileEvent:=CreateEvent(nil,FALSE,FALSE,nil);
  // Asynchronstruktur mit Ereignis besetzen
  Overlap.hEvent:=FileEvent;

  // Neues Ereignis erstellen, um später WaitForMultipleObjects abzubrechen
  // der Abbruch erfolgt von außen durch die Erzeugung des gleichen Events
  // welcher dann auf signaled gesetzt werden muß
  TermEvent:=TEvent.Create(nil,FALSE,FALSE,TermEvName);

  // Neues Ereignis erstellen, um später WaitForMultipleObjects abzubrechen
  // und den Thread auf suspendet zu setzen
  // der Abbruch erfolgt von außen durch die Erzeugung des gleichen Events
  // welcher dann auf signaled gesetzt werden muß
  SuspEvent:=TEvent.Create(nil,FALSE,FALSE,SuspEvName);

  // die drei Ereignishandles für WaitForMultipleObjects in ein Array füllen
  EventArray[0]:=FileEvent; // Ordneränderung
  EventArray[1]:=TermEvent.Handle; // Abbruch
  EventArray[2]:=SuspEvent.Handle; // Suspend

  // Rückgabepuffer für ReadDirectoryChangesW erstellen
  dwBufLen := 65535;
  pBuffer := AllocMem(dwBufLen);
  try
    // Ablauf starten ...
    while not terminated do begin
      // Ordnerüberwachung asynchron erstellen
      dwRead:=0;
      if ReadDirectoryChangesW(FhFile,pBuffer,dwBufLen,true,
                               FFilter, //FILE_NOTIFY_CHANGE_FILE_NAME or FILE_NOTIFY_CHANGE_DIR_NAME,
                               @dwRead,@Overlap,NIL) then
      begin
        // unendliches warten bis eines der Ereignisse eintritt
        WaitResult:=WaitForMultipleObjects(3,@EventArray,FALSE,infinite);
        // wenn das Warten beendet wird, dann ...
        case WaitResult of
          // ... weil sich etwas in den Ordnern getan hat
          WaitDir: begin
                   // Maske über den Puffer legen, um auf die Daten zuzugreifen
                   PInfo:= pBuffer;
                   // und dies wiederholen ...
                   repeat
                     // Offset zum folgenden Datensatz
                     dwNextOfs :=PInfo.dwNextEntryOffset;
                     // Aktion, die im Ordnerbaum sattfand
                     fAction :=PInfo.dwAction;
                     // Länge des betroffenen Ordners oder der Datei
                     dwFnLen :=PInfo.dwFileNameLength;
                     // Dateinamen in AnsiString umsetzen
                     fsFileName:=WideCharLenToString(@PInfo.dwFileName,dwFnLen div 2);
                     // Daten in den Haupttread übergeben
                     Synchronize(SendData);
                     // Maske auf den nächsten Datensatz verschieben
                     pChar(PInfo):=pChar(PInfo)+dwNextOfs;
                     // wenn keiner mehr vorhanden ist, beenden
                   until dwNextOfs=0;
                 end;
          // ... oder das Abbruchereignis eingetreten ist
          WaitTerm: Terminate;
          // ... oder das Ereignis zum suspendieren eingetreten ist
          WaitSusp: Suspend;
          else break;
        end;
      end;
    end;
  finally
    FreeMem(pBuffer,dwBufLen);
  end;
end;

destructor CtrlThread.Destroy;
begin // diverse Handles freigeben
  try
    if FhFile <> INVALID_HANDLE_VALUE then CloseHandle(FhFile);
    CloseHandle(FileEvent);
    TermEvent.Free;
    SuspEvent.Free;
  except
  end;
end;

// Daten an das Control-Objekt übergeben
procedure CtrlThread.SendData;
begin
  TFldrControl(Owner).EvAction:=FAction;
  TFldrControl(Owner).EvOrdner:=fsFileName;
  // und dort die Benachrichtigungsfunktion aufrufen
  TFldrControl(Owner).GetData;
end;

end.
Also dann das Ganze als Komponente registrieren un in des Formulat legen.
Die Ereignisbehandlungsroutine aufbauen, Pfad setzen und mit StartTread aktivieren.

Gruß, Manfred
Manfred Götze
  Mit Zitat antworten Zitat
Benutzerbild von Cylence
Cylence

Registriert seit: 2. Sep 2004
Ort: Allgäu
246 Beiträge
 
Delphi 7 Enterprise
 
#3

Re: ReadDirectoryChangesW

  Alt 17. Mär 2008, 08:33
Hi,

WOW Cool, danke das sieht perfekt aus werd ich dann gleich mal testen SUPER

THANX

Cylence
Tom
Just DO it
  Mit Zitat antworten Zitat
Benutzerbild von Cylence
Cylence

Registriert seit: 2. Sep 2004
Ort: Allgäu
246 Beiträge
 
Delphi 7 Enterprise
 
#4

Re: ReadDirectoryChangesW

  Alt 17. Mär 2008, 13:02
Hi,

ok klappt perfekt das teil, danke Dir.
nur eine frage noch, gehen da auch irgendwie mehrere davon gleichzeitig? Habs mal getestet aber irgendwie ging nur einer...


Gruß

tom
Tom
Just DO it
  Mit Zitat antworten Zitat
Ganymed

Registriert seit: 11. Jun 2003
Ort: Hameln
56 Beiträge
 
Delphi 7 Architect
 
#5

Re: ReadDirectoryChangesW

  Alt 26. Mär 2009, 10:03
Hallo!

Ich habe mir deinen Code auch mal "ausgeliehen" , bekomme aber fast immer bei CloseHandle(FhFile); im Destructor eine AV bzw. einen Memory-leak...

Muss man irgendwas bestimmtes machen, bevor man den freigibt?

Mein Code sieht grob so aus:
Delphi-Quellcode:
constructor TAutomatics.Create(AOwner: TControl; ASettings: TAutomaticsSetting; ASequenceIndex: Integer);
begin
  inherited Create;
  FOwner := AOwner;

  iSequenceIndex := ASequenceIndex;
  rSettings := ASettings;
  bEnabled := False;

  oFileQueue := TStringList.Create;
  oFolderControler := TFldrControl.Create(AOwner);
  oFolderControler.Folder := rSettings.sInputFolder;
  oFolderControler.OnGetResult := FolderControlEvent;
end;

destructor TAutomatics.Destroy;
begin
  oFolderControler.StopThread;
  oFolderControler.Free;
  oFileQueue.Free;
  inherited;
end;
Gestartet wird der Thread an anderer Stelle mit StartThread().

Achja, noch eine Frage:
Das Event triggert ja, sobald eine Datei erstellt wird. Wenn man nun eine sehr große Datei kopiert, triggert das Event, sobald der Dateiname da ist, und lange bevor die Datei komplett erstellt/kopiert wurde. Gibt es einen Trick, wie man ermitteln kann, ob die Datei vollständig erstellt wurde? Mit schwebt da was mit einer Schreife auf TFileStream.Create(..., fmShareExclusive) vor, bis der exklusive Zugriff erfolgreich ist...
  Mit Zitat antworten Zitat
Benutzerbild von MuTzE.Y85
MuTzE.Y85

Registriert seit: 11. Apr 2006
152 Beiträge
 
#6

AW: ReadDirectoryChangesW

  Alt 18. Mai 2014, 13:34
Ich muss das Thema mal aufleben lassen.

Ich bin dabei mir ein Tool zu schreiben, dass Ordner überwacht und diese bei Änderungen spiegelt. Das klappt soweit auch.
Dabei nutze ich die SHChangeNotify API. Damit kann ich mehrere Ordner gleichzeitig überwachen, jedoch kommt es ab und an vor, dass einige Änderungen nicht wahrgenommen oder weitergeleitet werden.

Jetzt habe ich schon gelesen, dass das normal ist, dass einige Events untergehen und die Methode "ReadDirectoryChangesW" dafür besser geeignet ist.

Die Frage ist jetzt: Kann man denn damit mehrere Verzeichnisse gleichzeitig überwachen?
LAN-PC: C2Q Q9550 @ 4004 MHz @ 1.232 V @ Mugen 2 | DFI LANParty JR P45-T2RS | G.Skill 4GB DDR2-1000 CL5 | ZOTAC GTX 280 @ GTX 285 @ 1.06 V | WD Caviar Blue 320GB / WD Caviar Black 640GB | BeQuiet DPP P7 450W | Antec Mini P180
  Mit Zitat antworten Zitat
hathor
(Gast)

n/a Beiträge
 
#7

AW: ReadDirectoryChangesW

  Alt 18. Mai 2014, 15:19
Dafür gibt es fertige Komponenten:
- HDDWatch
- DirectoryWatch

Für jedes Laufwerk eine Kompo aufs Formular:
Miniaturansicht angehängter Grafiken
hddwatch.jpg  

Geändert von hathor (18. Mai 2014 um 15:51 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von MuTzE.Y85
MuTzE.Y85

Registriert seit: 11. Apr 2006
152 Beiträge
 
#8

AW: ReadDirectoryChangesW

  Alt 18. Mai 2014, 15:34
Aha, und was machen die anders als die oben gepostete?

Sorry, aber deine Antwort bringt mir nix, denn meine Frage war eine Andere.
LAN-PC: C2Q Q9550 @ 4004 MHz @ 1.232 V @ Mugen 2 | DFI LANParty JR P45-T2RS | G.Skill 4GB DDR2-1000 CL5 | ZOTAC GTX 280 @ GTX 285 @ 1.06 V | WD Caviar Blue 320GB / WD Caviar Black 640GB | BeQuiet DPP P7 450W | Antec Mini P180
  Mit Zitat antworten Zitat
hathor
(Gast)

n/a Beiträge
 
#9

AW: ReadDirectoryChangesW

  Alt 18. Mai 2014, 15:52
Die Frage ist jetzt: Kann man denn damit mehrere Verzeichnisse gleichzeitig überwachen?
Das IST Deine Frage!
  Mit Zitat antworten Zitat
Benutzerbild von MuTzE.Y85
MuTzE.Y85

Registriert seit: 11. Apr 2006
152 Beiträge
 
#10

AW: ReadDirectoryChangesW

  Alt 18. Mai 2014, 16:05
Für jedes Laufwerk eine Kompo aufs Formular:
Ja und diesen Teil hätte ich mir vor der Bearbeitung deines Posts gewünscht

Problem ist nur, dass die Anzahl, der zu überwachenden Verzeichnisse ja bei der Entwicklung nicht vor liegt.
Das wird ja dann im Programm selbst festgelegt. Soll ja auch anpassbar sein.

Wie mache ich das dann?
Die Komponente zur Laufzeit erstellen, aber wie halte ich sie dann auseinander?

EDIT: Alles klar, habs hinbekommen mit einem Array.
LAN-PC: C2Q Q9550 @ 4004 MHz @ 1.232 V @ Mugen 2 | DFI LANParty JR P45-T2RS | G.Skill 4GB DDR2-1000 CL5 | ZOTAC GTX 280 @ GTX 285 @ 1.06 V | WD Caviar Blue 320GB / WD Caviar Black 640GB | BeQuiet DPP P7 450W | Antec Mini P180

Geändert von MuTzE.Y85 (19. Mai 2014 um 01:15 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2   

Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:17 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz