Конференция "WinAPI" » Отлавливаю изменения ФС. Почему изменение не ловится? [D7, WinXP]
 
  • AV © (09.04.12 11:13) [0]
    Поток смотрит за изменением и отсылает сообщение
    Создание-удаление-переименование отслеживается.
    Почему изменение файла не ловится?


      FFN: TFindFileNotify;

         FFN := TFindFileNotify.Create(True);
         FFN.FreeOnTerminate := True;
         FFN.HWND := Self.Handle;
         FFN.Msg := WM_USER;
         FFN.Ident := 1;
         FFN.MyDir := 'c:\1111\';
         FFN.AndSubFolder := True;
         FFN.Resume;

    procedure TForm1.WM_FFN(var Message: TMessage);
    begin
     Memo1.Lines.Add(StrPas(PAnsiChar(TMessage(Message).LParam)));
    =====
    unit uFileNotify;
    interface
    uses
    Classes, Windows;
    type
    PFileNotifyInformation = ^TFileNotifyInformation;
    TFileNotifyInformation = record
      NextEntryOffset : DWORD;
      Action          : DWORD;
      FileNameLength  : DWORD;
      FileName        : array[0..0] of WideChar;
    end;
    type
    TFindFileNotify = class(TThread)
    private     { Private declarations }
      FHWND: THandle;
      FMsg: THandle;
      FIdent: THandle;
      FMyDir: string;
      FAndSubFolder: Boolean;
      procedure SetHWND(const Value: THandle);
      procedure SetMsg(const Value: THandle);
      procedure SetIdent(const Value: THandle);
      procedure SetMyDir(const Value: string);
      procedure SetAndSubFolder(const Value: Boolean);
    protected
      procedure Execute; override;
    public
      property HWND:THandle  read FHWND write SetHWND;
      property Msg:THandle  read FMsg write SetMsg;
      property Ident:THandle  read FIdent write SetIdent;
      property MyDir:string  read FMyDir write SetMyDir;
      property AndSubFolder:Boolean read FAndSubFolder write SetAndSubFolder;
    end;
    implementation
    { TFindFileNotify }
    procedure TFindFileNotify.Execute;
    const
    BUF_SIZE = 2048;
    var
    hDir : THandle;
    lpBuf : Pointer;
    Ptr   : Pointer;
    cbReturn : Cardinal;
    FileName : PWideChar;
    S: string;
    begin
    hDir := CreateFile (PAnsiChar(FMyDir),
                       GENERIC_READ,
                       FILE_SHARE_READ or FILE_SHARE_WRITE or FILE_SHARE_DELETE,
                       nil,
                       OPEN_EXISTING,
                       FILE_FLAG_BACKUP_SEMANTICS,
                       0);
    if hDir = INVALID_HANDLE_VALUE then
    begin
      S := 'hDir = INVALID_HANDLE_VALUE';
      if HWND <> 0 then
        SendMessage(HWND, Msg, Ident, LPARAM(PChar(s)));
      exit;
    end;
    GetMem(lpBuf, BUF_SIZE);
    repeat
      ZeroMemory(lpBuf, BUF_SIZE);
      if not ReadDirectoryChangesW(hDir,
                                 lpBuf,
                                 BUF_SIZE,
                                 FAndSubFolder, // true c подкаталогами
                                 FILE_NOTIFY_CHANGE_FILE_NAME,
                                 @cbReturn,
                                 nil,
                                 nil) then
        Break;
      Ptr := lpBuf;
      repeat
       S := '';
       GetMem(FileName, PFileNotifyInformation(Ptr).FileNameLength + 2);
       ZeroMemory(FileName, PFileNotifyInformation(Ptr).FileNameLength+2);
       lstrcpynW(FileName,
                 PFileNotifyInformation(Ptr).FileName,
                 PFileNotifyInformation(Ptr).FileNameLength div 2 + 1);
       S := MyDir + FileName;
       FreeMem(FileName);
       case PFileNotifyInformation(Ptr).Action of
         FILE_ACTION_ADDED    : S := '[Создан]' + S;
         FILE_ACTION_REMOVED  : S := '[Удален]' + S;
         FILE_ACTION_MODIFIED : S := '[Изменен]' + S;
         FILE_ACTION_RENAMED_OLD_NAME :  S := '[ДоПереименован]' + S;
         FILE_ACTION_RENAMED_NEW_NAME :   S := '[ПослеПереименован]' + S;
         else S := '[Непонятно]' + S;
       end;
       if S <> '' then
       begin
         if (HWND <> 0) and not(Terminated) then
           SendMessage(HWND, Msg, Ident, LPARAM(PChar(S)));
         S := '';
       end;
       if PFileNotifyInformation(Ptr).NextEntryOffset = 0 then
         Break else
         Inc(Cardinal(Ptr),PFileNotifyInformation(Ptr).NextEntryOffset);
      until Terminated;
    until Terminated;
    FreeMem(lpBuf);
    end;

    procedure TFindFileNotify.SetAndSubFolder(const Value: Boolean);
    begin
    FAndSubFolder := Value;
    end;

    procedure TFindFileNotify.SetHWND(const Value: THandle);
    begin
    FHWND := Value;
    end;

    procedure TFindFileNotify.SetIdent(const Value: THandle);
    begin
    FIdent := Value;
    end;

    procedure TFindFileNotify.SetMsg(const Value: THandle);
    begin
    FMsg := Value;
    end;

    procedure TFindFileNotify.SetMyDir(const Value: string);
    begin
    FMyDir := Value;
    end;
    end.

  • begin...end © (09.04.12 11:19) [1]
    > if not ReadDirectoryChangesW(hDir,
    >                              lpBuf,
    >                              BUF_SIZE,
    >                              FAndSubFolder, // true c подкаталогами
    >                              FILE_NOTIFY_CHANGE_FILE_NAME,
    >                              @cbReturn,
    >                              nil,
    >                              nil) then

    FILE_NOTIFY_CHANGE_FILE_NAME
    0x00000001

    Any file name change in the watched directory or subtree causes a change notification wait operation to return. Changes include renaming, creating, or deleting a file.

    (c) MSDN
  • AV © (09.04.12 14:22) [2]
    черт..
    спасибо
  • AV © (18.04.12 10:30) [3]
    только сейчас руки дошли
    надо так, значит:
    (исправлю по ответу, заодно пусть будет. Может потом найду, если потеряю. Вроде, модуль целиком запостил в прошлый раз)

    procedure TForm1.btn1Click(Sender: TObject);
    begin
     if B then
       FFN.Terminate else
       begin
         FFN := TFindFileNotify.Create(True);
         FFN.FreeOnTerminate := True;
         FFN.HWND := Self.Handle;
         FFN.Msg := WM_USER;
         FFN.Ident := 1;
         FFN.MyDir := edt1.Text;
         if cbAndSubFolder.Checked then
           FFN.AndSubFolder := True else
           FFN.AndSubFolder := False;
         FFN.WatchFind := 0; // новое св-во
         if cbCreateDelRename.Checked then
           FFN.WatchFind := FFN.WatchFind or FILE_NOTIFY_CHANGE_FILE_NAME;
         if cbChangeContent.Checked then
           FFN.WatchFind := FFN.WatchFind or FILE_NOTIFY_CHANGE_SIZE;
         if cbOtherChange.Checked then
           FFN.WatchFind := FFN.WatchFind or FILE_NOTIFY_CHANGE_ATTRIBUTES or
                            FILE_NOTIFY_CHANGE_LAST_WRITE or FILE_NOTIFY_CHANGE_LAST_ACCESS or
                            FILE_NOTIFY_CHANGE_SECURITY or FILE_NOTIFY_CHANGE_CREATION;
         FFN.Resume;
       end;
     B := not(b);
     if B then
       btn1.Caption := 'Стоп' else
       btn1.Caption := 'Старт';
    end;



    и, соответственно,

       if not ReadDirectoryChangesW(hDir,       // http://msdn.microsoft.com/en-us/library/windows/desktop/aa365465%28v=vs.85%29.aspx
                                  lpBuf,
                                  BUF_SIZE,
                                  FAndSubFolder,
                                  FWatchFind,
                                  @cbReturn,
                                  nil,
                                  nil) then
         Break;

 
Конференция "WinAPI" » Отлавливаю изменения ФС. Почему изменение не ловится? [D7, WinXP]
Есть новые Нет новых   [134430   +2][b:0][p:0.005]