怎么用Delphi来监控当前是否有文件正在被复制或移动??????
如果有文件正在复制或移动怎样知道当前正在复制或移动是什么文件和文件路径?????以上的是不是应该判断是否有文件贴粘好点呢?????比如:我现在复制三个文件,a.txt和b.dat和c.mp3,注意是三个文件同时复制,然后贴粘的时候程序就判断当前正在贴粘的是什么文件,文件全路径????可以做到这样子吗?
我只知道用一个线程来监控,其他就不是很懂了,请高手指教!!!!!最好能给点代码,因为这个比较急,所以我不想再花时间来研究,要是实在没有代码,给点什么提示也行,总比什么都没有好。

解决方案 »

  1.   

    就2个方法:
    1)API hook:SHFileOperation,CopyFile等API
    2)Shell Hook,可以监控Shell事件
      

  2.   

    相比较Hook用一个线程来监控实现起来要简单些
      

  3.   

    不知道TShellChangeNotifier,是否能够满足你的要求,delphi的samples下的组件
      

  4.   

    //通过ShellAPI函数来实现比较科学~~
    //注册一个事件响应~~
    //代码如下~~
    //zswang
    unit unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, ShlObj, ShellAPI;const
      WM_SHNOTIFY = WM_USER + 10;type
      TForm1 = class(TForm)
        MemoNotifyLog: TMemo;
        procedure FormCreate(Sender: TObject);
        procedure FormDestroy(Sender: TObject);
      private
        { Private declarations }
        FNotifyHandle: THandle;
        procedure WMSHNOTIFY(var Msg: TMessage); message WM_SHNOTIFY;
      public
        { Public declarations }
      end;var
      FOrm1: Tform1;implementation{$WARNINGS OFF}
    uses FileCtrl;{$R *.dfm}type
      NOTIFYREGISTER = packed record
        pidlPath: PItemIDList;
        bWatchSubtree: BOOL;
      end;
      PNotifyRegister = ^NOTIFYREGISTER;  function SHChangeNotifyRegister(hWnd: HWND; dwFlags: Integer;
        wEventMask: Cardinal; uMsg: UINT; cItems: Integer;
        lpItems: PNotifyRegister): HWND; stdcall; external Shell32 index 2;  function SHChangeNotifyDeregister(hWnd: HWND): Boolean; stdcall;
        external Shell32 index 4;  function SHILCreateFromPath(pszPath: PChar; ppidl: PItemIDList;
        rgflnOut: PDWORD): HResult; stdcall; external Shell32 index 28;
    {$WARNINGS ON}procedure Tform1.FormCreate(Sender: TObject);
    var
      vNotifyRegister: NOTIFYREGISTER;
      vAttributes: WORD;
      vItemIDList: PItemIDList;
      Dir: string;
    const
      SELDIRHELP = 1000;
    begin
      Dir := '我的电脑';
    //if SelectDirectory(Dir, [sdAllowCreate, sdPerformCreate, sdPrompt],SELDIRHELP) then ;
      Caption := '目录监视:' + Dir;
      SHILCreatefromPath(PChar(Dir), @vItemIDList, @vAttributes);
      vNotifyRegister.pidlPath := vItemIDList;
      vNotifyRegister.bWatchSubtree := True;  FNotifyHandle := SHChangeNotifyRegister(Handle, SHCNF_TYPE or SHCNF_IDLIST,
        SHCNE_ALLEVENTS or SHCNE_INTERRUPT, WM_SHNOTIFY, 1, @vNotifyRegister);  MemoNotifyLog.Clear;
    end;procedure Tform1.FormDestroy(Sender: TObject);
    begin
      SHChangeNotifyDeregister(FNotifyHandle);
    end;procedure Tform1.WMSHNOTIFY(var Msg: TMessage);
    type
      PSHNOTIFYSTRUCT = ^SHNOTIFYSTRUCT;
      SHNOTIFYSTRUCT = packed record
        dwItem1: PItemIDList;
        dwItem2: PItemIDList;
      end;
    var
      vBuffer: array[0..MAX_PATH] of Char;
      pidlItem: PSHNOTIFYSTRUCT;
      S: string;
    begin
      pidlItem := PSHNOTIFYSTRUCT(Msg.wParam);
      SHGetPathFromIDList(pidlItem.dwItem1, vBuffer);
      S := vBuffer;
      SHGetPathFromIDList(pidlItem.dwItem2, vBuffer);
      case Msg.lParam of //根据参数设置提示消息
        SHCNE_RENAMEITEM: S := '重命名文件' + S + '为' + vBuffer;
        SHCNE_CREATE: S := '建立文件 文件名:' + S;
        SHCNE_DELETE: S := '删除文件 文件名:' + S;
        SHCNE_MKDIR: S := '新建目录 目录名:' + S;
        SHCNE_RMDIR: S := '删除目录 目录名:' + S;
        SHCNE_MEDIAINSERTED: S := S + '中插入可移动存储介质';
        SHCNE_MEDIAREMOVED: S := S + '中移去可移动存储介质' + S + ' ' + vBuffer;
        SHCNE_DRIVEREMOVED: S := '移去驱动器' + S;
        SHCNE_DRIVEADD: S := '添加驱动器' + S;
        SHCNE_NETSHARE: S := '改变目录' + S + '的共享属性';
        SHCNE_ATTRIBUTES: S := '改变文件目录属性 文件名' + S;
        SHCNE_UPDATEDIR: S := '更新目录' + S;
        SHCNE_UPDATEITEM: S := '更新文件 文件名:' + S;
        SHCNE_SERVERDISCONNECT: S := '断开与服务器的连接' + S + ' ' + vBuffer;
        SHCNE_UPDATEIMAGE: S := 'SHCNE_UPDATEIMAGE';
        SHCNE_DRIVEADDGUI: S := 'SHCNE_DRIVEADDGUI';
        SHCNE_RENAMEFOLDER: S := '重命名文件夹' + S + '为' + vBuffer;
        SHCNE_FREESPACE: S := '磁盘空间大小改变';
        SHCNE_ASSOCCHANGED: S := '改变文件关联';
      else S := '未知操作' + IntToStr(Msg.lParam);
      end;
      MemoNotifyLog.Lines.Add(DateTimeTostr(Now)+' '+S);
    end;end.
      

  5.   

    object Form1: TForm1
      Left = 271
      Top = 191
      Width = 435
      Height = 421
      ActiveControl = ePath
      Caption = 'ReadDirectoryChangesW demo'
      Color = clBtnFace
      Font.Charset = DEFAULT_CHARSET
      Font.Color = clWindowText
      Font.Height = -11
      Font.Name = 'MS Sans Serif'
      Font.Style = []
      FormStyle = fsStayOnTop
      OldCreateOrder = True
      Position = poScreenCenter
      OnCreate = FormCreate
      OnDestroy = FormDestroy
      PixelsPerInch = 96
      TextHeight = 13
      object lbEvents: TListBox
        Left = 0
        Top = 212
        Width = 427
        Height = 175
        Align = alClient
        ItemHeight = 13
        TabOrder = 0
      end
      object Panel1: TPanel
        Left = 0
        Top = 0
        Width = 427
        Height = 212
        Align = alTop
        BevelOuter = bvNone
        TabOrder = 1
        object Label1: TLabel
          Left = 6
          Top = 43
          Width = 97
          Height = 13
          Caption = 'Directory to monitor :'
        end
        object CJLabel1: TLabel
          Left = 113
          Top = 8
          Width = 189
          Height = 24
          Caption = 'Directory Monitoring'
          Font.Charset = DEFAULT_CHARSET
          Font.Color = clNavy
          Font.Height = -19
          Font.Name = 'MS Sans Serif'
          Font.Style = [fsBold]
          ParentFont = False
        end
        object SpeedButton1: TSpeedButton
          Left = 399
          Top = 58
          Width = 21
          Height = 21
          Glyph.Data = {
            F6000000424DF600000000000000760000002800000010000000100000000100
            0400000000008000000000000000000000001000000010000000000000000000
            80000080000000808000800000008000800080800000C0C0C000808080000000
            FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF00777777777777
            77777777777777777777000000000007777700333333333077770B0333333333
            07770FB03333333330770BFB0333333333070FBFB000000000000BFBFBFBFB07
            77770FBFBFBFBF0777770BFB0000000777777000777777770007777777777777
            7007777777770777070777777777700077777777777777777777}
          OnClick = ePathDblClick
        end
        object ePath: TEdit
          Left = 5
          Top = 58
          Width = 394
          Height = 21
          Hint = 'Double-Click to display a browse dialog'
          ParentShowHint = False
          ShowHint = True
          TabOrder = 0
          OnDblClick = ePathDblClick
        end
        object bStart: TButton
          Left = 269
          Top = 184
          Width = 75
          Height = 25
          Caption = 'Start'
          TabOrder = 1
          OnClick = bStartClick
        end
        object bStop: TButton
          Left = 349
          Top = 184
          Width = 75
          Height = 25
          Caption = 'Stop'
          Enabled = False
          TabOrder = 2
          OnClick = bStopClick
        end
        object ckWatchSubTree: TCheckBox
          Left = 4
          Top = 184
          Width = 221
          Height = 17
          Caption = 'Also watch sub-directories events'
          TabOrder = 3
        end
        object GroupBox1: TGroupBox
          Left = 4
          Top = 81
          Width = 420
          Height = 100
          Caption = 'Events that you want to monitor'
          TabOrder = 4
          object ckMonitorFileName: TCheckBox
            Left = 9
            Top = 19
            Width = 199
            Height = 17
            Caption = 'File Created/Deleted/Renamed'
            Checked = True
            State = cbChecked
            TabOrder = 0
          end
          object ckMonitorDirName: TCheckBox
            Left = 9
            Top = 38
            Width = 199
            Height = 17
            Caption = 'Directory Created/Renamed/Deleted'
            TabOrder = 1
          end
          object ckMonitorAttributes: TCheckBox
            Left = 9
            Top = 56
            Width = 199
            Height = 17
            Caption = 'File or Directory Attributes changed'
            TabOrder = 2
          end
          object ckMonitorSize: TCheckBox
            Left = 9
            Top = 75
            Width = 199
            Height = 17
            Caption = 'File size changed'
            TabOrder = 3
          end
          object ckMonitorLastWrite: TCheckBox
            Left = 215
            Top = 38
            Width = 201
            Height = 17
            Caption = 'File or Dir Last Write Date changed'
            Checked = True
            State = cbChecked
            TabOrder = 4
          end
          object ckMonitorSecurity: TCheckBox
            Left = 215
            Top = 56
            Width = 201
            Height = 17
            Caption = 'File or Dir Security Attributes changed'
            TabOrder = 5
          end
          object ckMonitorCreationDate: TCheckBox
            Left = 215
            Top = 19
            Width = 201
            Height = 17
            Caption = 'File or Dir Creation Date changed'
            TabOrder = 6
          end
          object ckMonitorLastAccess: TCheckBox
            Left = 215
            Top = 75
            Width = 201
            Height = 17
            Caption = 'File or Dir Last Access Date changed'
            TabOrder = 7
          end
        end
      end
    end
      

  6.   

    unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
      StdCtrls, ExtCtrls, Buttons;type
      TForm1 = class(TForm)
        lbEvents: TListBox;
        Panel1: TPanel;
        Label1: TLabel;
        ePath: TEdit;
        CJLabel1: TLabel;
        bStart: TButton;
        bStop: TButton;
        ckWatchSubTree: TCheckBox;
        GroupBox1: TGroupBox;
        ckMonitorFileName: TCheckBox;
        ckMonitorDirName: TCheckBox;
        ckMonitorAttributes: TCheckBox;
        ckMonitorSize: TCheckBox;
        ckMonitorLastWrite: TCheckBox;
        ckMonitorSecurity: TCheckBox;
        ckMonitorCreationDate: TCheckBox;
        ckMonitorLastAccess: TCheckBox;
        SpeedButton1: TSpeedButton;
        procedure bStartClick(Sender: TObject);
        procedure bStopClick(Sender: TObject);
        procedure FormDestroy(Sender: TObject);
        procedure FormCreate(Sender: TObject);
        procedure ePathDblClick(Sender: TObject);
      private
        { D閏larations priv閑s }
        FDirectoryHandle: THandle;
        FNotificationBuffer: array[0..4096] of Byte;
        FWatchThread: TThread;
        FNotifyFilter: DWORD;
        FOverlapped: TOverlapped;
        FPOverlapped: POverlapped;
        FBytesWritten: DWORD;
        FCompletionPort: THandle;
      public
        { D閏larations publiques }
      end;var
      Form1: TForm1;type
      PFileNotifyInformation = ^TFileNotifyInformation;
      TFileNotifyInformation = record
        NextEntryOffset: DWORD;
        Action: DWORD;
        FileNameLength: DWORD;
        FileName: array[0..0] of WideChar;
      end;const
      FILE_LIST_DIRECTORY   = $0001;const
      SAction: array[FILE_ACTION_ADDED..FILE_ACTION_RENAMED_NEW_NAME] of String =
      ( 'ADDED %s',
        'DELETED %s',
        'MODIFIED %s',
        'RENAMED %s [...]',
        '[...] into %s');implementation{$R *.DFM}uses
      ShlObj, ActiveX;type
      TWaitThread = class(TThread)
      private
        FForm: TForm1;
        procedure HandleEvent;
      protected
        procedure Execute; override;
      public
        constructor Create(Form: TForm1);
      end;constructor TWaitThread.Create(Form: TForm1);
    begin
      inherited Create(True);
      FForm := Form;
      FreeOnTerminate := False;
    end;procedure TWaitThread.HandleEvent;
    var
      FileOpNotification: PFileNotifyInformation;
      Offset: Longint;
    begin
      with FForm do
      begin
        Pointer(FileOpNotification) := @FNotificationBuffer[0];
        repeat
          Offset := FileOpNotification^.NextEntryOffset;
          lbEvents.Items.Add(Format(SAction[FileOpNotification^.Action], [WideCharToString(@(FileOpNotification^.FileName))]));
          PChar(FileOpNotification) := PChar(FileOpNotification)+Offset;
        until Offset=0;
      end;
    end;procedure TWaitThread.Execute;
    var
      numBytes: DWORD;
      cbOffset: DWORD;
      CompletionKey: DWORD;
    begin
      while not Terminated do
      begin
        GetQueuedCompletionStatus( FForm.FCompletionPort, numBytes, CompletionKey, FForm.FPOverlapped, INFINITE);
        if CompletionKey <> 0 then
        begin
          Synchronize(HandleEvent);
          with FForm do
          begin
            FBytesWritten := 0;
            ZeroMemory(@FNotificationBuffer, SizeOf(FNotificationBuffer));
            ReadDirectoryChanges(FDirectoryHandle, @FNotificationBuffer, SizeOf(FNotificationBuffer), ckWatchSubTree.Checked, FNotifyFilter, @FBytesWritten, @FOverlapped, nil);
          end;
        end
        else
          Terminate;
      end;
    end;procedure TForm1.bStartClick(Sender: TObject);
    begin
      FNotifyFilter := 0;
      if ckMonitorFileName.Checked then
        FNotifyFilter := FNotifyFilter or FILE_NOTIFY_CHANGE_FILE_NAME;
      if ckMonitorDirName.Checked then
        FNotifyFilter := FNotifyFilter or FILE_NOTIFY_CHANGE_DIR_NAME;
      if ckMonitorAttributes.Checked then
        FNotifyFilter := FNotifyFilter or FILE_NOTIFY_CHANGE_ATTRIBUTES;
      if ckMonitorSize.Checked then
        FNotifyFilter := FNotifyFilter or FILE_NOTIFY_CHANGE_SIZE;
      if ckMonitorLastWrite.Checked then
        FNotifyFilter := FNotifyFilter or FILE_NOTIFY_CHANGE_LAST_WRITE;
      if ckMonitorLastAccess.Checked then
        FNotifyFilter := FNotifyFilter or FILE_NOTIFY_CHANGE_LAST_ACCESS;
      if ckMonitorCreationDate.Checked then
        FNotifyFilter := FNotifyFilter or FILE_NOTIFY_CHANGE_CREATION;
      if ckMonitorSecurity.Checked then
        FNotifyFilter := FNotifyFilter or FILE_NOTIFY_CHANGE_SECURITY;
      if FNotifyFilter = 0 then
      begin
         ShowMessage('Vous devez monitorer au moins 1 関閚ement !');
         exit;
      end;
      lbEvents.Clear;
      FDirectoryHandle := CreateFile(PChar(ePath.Text),
        FILE_LIST_DIRECTORY,
        FILE_SHARE_READ or FILE_SHARE_WRITE or FILE_SHARE_DELETE,
        nil,
        OPEN_EXISTING,
        FILE_FLAG_BACKUP_SEMANTICS or FILE_FLAG_OVERLAPPED,
        0);
      if FDirectoryHandle = INVALID_HANDLE_VALUE then
      begin
        beep;
        FDirectoryHandle := 0;
        ShowMessage(SysErrorMessage(GetLastError));
        exit;
      end;
      FCompletionPort := CreateIoCompletionPort(FDirectoryHandle, 0, Longint(pointer(self)), 0);
      ZeroMemory(@FNotificationBuffer, SizeOf(FNotificationBuffer));
      FBytesWritten := 0;
      if not ReadDirectoryChanges(FDirectoryHandle, @FNotificationBuffer, SizeOf(FNotificationBuffer), ckWatchSubTree.Checked, FNotifyFilter, @FBytesWritten, @FOverlapped, nil) then
      begin
        CloseHandle(FDirectoryHandle);
        FDirectoryHandle := 0;
        CloseHandle(FCompletionPort);
        FCompletionPort := 0;
        ShowMessage(SysErrorMessage(GetLastError));
        exit;
      end;
      ePath.Enabled := False;
      bStart.Enabled := False;
      bStop.Enabled := True;
      FWatchThread := TWaitThread.Create(self);
      TWaitThread(FWatchThread).Resume;
    end;procedure TForm1.bStopClick(Sender: TObject);
    begin
      if FCompletionPort = 0 then
        exit;
      PostQueuedCompletionStatus(FCompletionPort, 0, 0, nil);
      FWatchThread.WaitFor;
      FWatchThread.Free;
      CloseHandle(FDirectoryHandle);
      FDirectoryHandle := 0;
      CloseHandle(FCompletionPort);
      FCompletionPort := 0;
      ePath.Enabled := True;
      bStart.Enabled := True;
      bStop.Enabled := False;
    end;procedure TForm1.FormDestroy(Sender: TObject);
    begin
      bStop.Click;
    end;procedure TForm1.FormCreate(Sender: TObject);
    begin
      FCompletionPort := 0;
      FDirectoryHandle := 0;
      FPOverlapped := @FOverlapped;
      ZeroMemory(@FOverlapped, SizeOf(FOverlapped));
    end;procedure TForm1.ePathDblClick(Sender: TObject);
    var
      SelectionPIDL: PItemIDList;
      BrowseInfo: TBrowseInfo;
      ShellAllocator: IMalloc;
      PathBuffer: array[0..MAX_PATH] of Char;
    begin
      // simplest implementation of BrowseForFolder
      // to get more information refer to MSDN Library or Check Brad Stower's excellent site www.delphifreestuff.com
      ZeroMemory(@BrowseInfo, SizeOf(BrowseInfo));
      BrowseInfo.hwndOwner := Handle;
      BrowseInfo.ulFlags := BIF_RETURNONLYFSDIRS;
      CoInitialize(nil);
      try
        SelectionPIDL := ShBrowseForFolder(BrowseInfo);
        if SelectionPIDL <> nil then
        try
          ZeroMemory(@PathBuffer, SizeOf(PathBuffer));
          if not SHGetPathFromIDList(SelectionPIDL, @PathBuffer) then
          begin
            beep;
            exit;
          end;
          ePath.Text := StrPas(@PathBuffer[0]);
        finally
          if SHGetMalloc(ShellAllocator) = 0 then
          begin
            ShellAllocator.Free(SelectionPIDL);
            ShellAllocator := nil;
          end;
        end;
      finally
        CoUnInitialize;
      end;
    end;end.
      

  7.   

    to zswangII(伴水清清)(一贴不灌,何以灌天下?) :
    你好,我是用shellapi来做的,能不能在复制文件的时间获取源路径文件,也就是这个文件是从那里复制过来的,复制贴粘文件的时候他会执行:SHCNE_CREATE: S := '建立文件 文件名:' + S; 可是那个S只是目标文件路径,怎么取得当前这个S目标文件的原路径文件,谢谢!
      

  8.   

    估计能通过拦截api实现你们的功能,这我就没时间弄鸟
      

  9.   

    to xthmpro_ch:
    网上只有ICopyHook监控文件夹,没有监控文件来的。