检测Windows Shell更改 [英] detecting windows shell changes

查看:51
本文介绍了检测Windows Shell更改的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对使用C Builder的知识非常有限,能否给我一个示例或指向我的教程,该教程显示如何在Delphi中使用FindNextChangeNotification,或者,如果可能的话,如何在delphi中使用C组件?

I have very limited knowledge of using C Builder, could you give me an example or point me to tutorial showing how to use FindNextChangeNotification in Delphi or ,if it is possible, how to use the C component in delphi?

推荐答案

ReadDirectoryChanges似乎是我想要的功能.这是我尝试使用mghie的代码为什么ReadDirectoryChangesW忽略事件?

The ReadDirectoryChanges seems to be the function that I am looking for. Here is my attempt using mghie's code Why does ReadDirectoryChangesW omit events?

我的目的是监视在Unit1中看到的目录/路径或文件.每当检测到位置发生变化时,我只希望弹出一个简单的showmessage对话.我找不到应该将通知程序或函数传递给的位置.Unit2只是保留了mghie中未更改的代码.当我编译该项目并在目录中进行简单更改时,什么也没有发生.我正确使用了ReadDirectoryChanges吗?

My objective here is to monitor the directory/path or file you will see in Unit1. I just want a simple showmessage dialogue to popup whenever a change at the location is detected. I can't find where I am supposed to pass my notification procedure or function. Unit2 just holds the unchanged code from mghie. When I compile this project and make a simple change in the directory nothing happens. I am using the ReadDirectoryChanges correctly?

这是Unit1:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Unit2;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  fthread:TWatcherthread;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
//start directory or file watch here
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
   fThread := TWatcherThread.Create('C:\Users\abe\Desktop\statcious\mitsu\Demo\abc.txt');

end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
   if fThread <> nil then begin
    TWatcherThread(fThread).Shutdown;
    fThread.Free;
  end;
end;

end.

这里是Unit2:

unit Unit2;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

type
  TWatcherThread = class(TThread)
  private
    fChangeHandle: THandle;
    fDirHandle: THandle;
    fShutdownHandle: THandle;
  protected
    procedure Execute; override;
  public
    constructor Create(ADirectoryToWatch: string);
    destructor Destroy; override;

    procedure Shutdown;

  end;

type
  TForm2 = class(TForm)
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form2: TForm2;

implementation

{$R *.dfm}

constructor TWatcherThread.Create(ADirectoryToWatch: string);
const
  FILE_LIST_DIRECTORY = 1;
begin
  inherited Create(TRUE);
  fChangeHandle := CreateEvent(nil, FALSE, FALSE, nil);
  fDirHandle := CreateFile(PChar(ADirectoryToWatch),
    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);
  fShutdownHandle := CreateEvent(nil, FALSE, FALSE, nil);
  Resume;
end;

destructor TWatcherThread.Destroy;
begin
  if fDirHandle <> INVALID_HANDLE_VALUE then
    CloseHandle(fDirHandle);
  if fChangeHandle <> 0 then
    CloseHandle(fChangeHandle);
  if fShutdownHandle <> 0 then
    CloseHandle(fShutdownHandle);
  inherited Destroy;
end;

procedure TWatcherThread.Execute;
type
  PFileNotifyInformation = ^TFileNotifyInformation;
  TFileNotifyInformation = record
    NextEntryOffset: DWORD;
    Action: DWORD;
    FileNameLength: DWORD;
    FileName: WideChar;
  end;
const
  BufferLength = 65536;
var
  Filter, BytesRead: DWORD;
  InfoPointer: PFileNotifyInformation;
  Offset, NextOffset: DWORD;
  Buffer: array[0..BufferLength - 1] of byte;
  Overlap: TOverlapped;
  Events: array[0..1] of THandle;
  WaitResult: DWORD;
  FileName, s: string;
begin
  if fDirHandle <> INVALID_HANDLE_VALUE then begin
    Filter := FILE_NOTIFY_CHANGE_FILE_NAME or FILE_NOTIFY_CHANGE_DIR_NAME
      or FILE_NOTIFY_CHANGE_SIZE or FILE_NOTIFY_CHANGE_LAST_WRITE;

    FillChar(Overlap, SizeOf(TOverlapped), 0);
    Overlap.hEvent := fChangeHandle;

    Events[0] := fChangeHandle;
    Events[1] := fShutdownHandle;

    while not Terminated do begin
      if ReadDirectoryChangesW (fDirHandle, @Buffer[0], BufferLength, TRUE,
        Filter, @BytesRead, @Overlap, nil)
      then begin
        WaitResult := WaitForMultipleObjects(2, @Events[0], FALSE, INFINITE);
        if WaitResult = WAIT_OBJECT_0 then begin
          InfoPointer := @Buffer[0];
          Offset := 0;
          repeat
            NextOffset := InfoPointer.NextEntryOffset;
            FileName := WideCharLenToString(@InfoPointer.FileName,
              InfoPointer.FileNameLength);
            SetLength(FileName, StrLen(PChar(FileName)));
            s := Format('[%d] Action: %.8xh, File: "%s"',
               [Offset, InfoPointer.Action, FileName]);
            OutputDebugString(PChar(s));
            PByte(InfoPointer) := PByte(DWORD(InfoPointer) + NextOffset);
            Offset := Offset + NextOffset;
          until NextOffset = 0;
        end;
      end;
    end;
  end;
end;

procedure TWatcherThread.Shutdown;
begin
  Terminate;
  if fShutdownHandle <> 0 then
    SetEvent(fShutdownHandle);
end;

end.

这篇关于检测Windows Shell更改的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆