WEB开发网
开发学院软件开发VC 目录监测 阅读

目录监测

 2006-07-20 11:39:18 来源:WEB开发网   
核心提示:本文示例源代码或素材下载 C# 中有类 FileSystemWatcher 不但能够知道指定目录树中的文件/目录的改变,而且能够知道是哪个文件/目录在改变,目录监测,而我用FindFirstChangeNotification等Win API 却不能实现第二个功能,虚耗了不少时间,只想睡觉,所以贴出来抛砖引玉,

本文示例源代码或素材下载

C# 中有类 FileSystemWatcher 不但能够知道指定目录树中的文件/目录的改变,而且能够知道是哪个文件/目录在改变,而我用FindFirstChangeNotification等Win API 却不能实现第二个功能,虚耗了不少时间,昨日在msdn中发现 ReadDirectoryChangesW 是可行的,特封装一下,请大家斧正。// 名称: FileSystemWatcher
// 功能: 监测指定目录中的文件/目录的改变
// 环境要求: Requires Windows NT 3.51 SP3 or later, and Unsupported Windows 95/98.
// 版权申明: 可任意拷贝、修改、发布
// 作者: 周星星
// 日期: 2003-08-07
// 说明: 未做测试
// VCKBASE.COM
#define _WIN32_WINNT 0x0500
#include <windows.h>
#include <string>
#include <cassert>
enum ACTION { ADDED=1, REMOVED=2, MODIFIED=3, RENAMED=4 };
class FileSystemWatcher
{
public:
  typedef void (__stdcall *LPDEALFUNCTION)( ACTION act, std::string filename1, std::string filename2 );
  bool Run( std::string path, LPDEALFUNCTION dealfun )
  {
    WatchedDir = path;
    DealFun = dealfun;
    DWORD ThreadId;
    hThread=CreateThread( NULL,0,Routine,this,0,&ThreadId );
    return NULL!=hThread;
  }
  void Close()
  {
    if( NULL != hThread )
    {
      TerminateThread( hThread, 0 );
      hThread = NULL;
    }
    if( INVALID_HANDLE_VALUE != hDir )
    {
      CloseHandle( hDir );
      hDir = INVALID_HANDLE_VALUE;
    }
  }
  FileSystemWatcher() : DealFun(NULL), hThread(NULL), hDir(INVALID_HANDLE_VALUE)
  {
  }
  ~FileSystemWatcher()
  {
    Close();
  }
private:
  std::string WatchedDir;
  LPDEALFUNCTION DealFun;
  HANDLE hThread;
  HANDLE hDir;
private:
  FileSystemWatcher( const FileSystemWatcher& );
  FileSystemWatcher operator=( const FileSystemWatcher );
private:
  static DWORD WINAPI Routine( LPVOID lParam )
  {
    FileSystemWatcher* obj = (FileSystemWatcher*)lParam;
    obj->hDir = CreateFile(
      obj->WatchedDir.c_str(),
      GENERIC_READ|GENERIC_WRITE,
      FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
      NULL,
      OPEN_EXISTING,
      FILE_FLAG_BACKUP_SEMANTICS,
      NULL
    );
    if( INVALID_HANDLE_VALUE == obj->hDir ) return false;
    char buf[ 2*(sizeof(FILE_NOTIFY_INFORMATION)+MAX_PATH) ];
    FILE_NOTIFY_INFORMATION* pNotify=(FILE_NOTIFY_INFORMATION *)buf;
    DWORD BytesReturned;
    while(true)
    {
      if( ReadDirectoryChangesW( obj->hDir,
        pNotify,
        sizeof(buf),
        true,
        FILE_NOTIFY_CHANGE_FILE_NAME|
        FILE_NOTIFY_CHANGE_DIR_NAME|
        FILE_NOTIFY_CHANGE_ATTRIBUTES|
        FILE_NOTIFY_CHANGE_SIZE|
        FILE_NOTIFY_CHANGE_LAST_WRITE|
        FILE_NOTIFY_CHANGE_LAST_ACCESS|
        FILE_NOTIFY_CHANGE_CREATION|
        FILE_NOTIFY_CHANGE_SECURITY,
        &BytesReturned,
        NULL,
        NULL ) )
      {
        char tmp[MAX_PATH], str1[MAX_PATH], str2[MAX_PATH];
        memset( tmp, 0, sizeof(tmp) );
        WideCharToMultiByte( CP_ACP,0,pNotify->FileName,pNotify->FileNameLength/2,tmp,99,NULL,NULL );
        strcpy( str1, tmp );
        if( 0 != pNotify->NextEntryOffset )
        {
          PFILE_NOTIFY_INFORMATION p = (PFILE_NOTIFY_INFORMATION)((char*)pNotify+pNotify->NextEntryOffset);
          memset( tmp, 0, sizeof(tmp) );
          WideCharToMultiByte( CP_ACP,0,p->FileName,p->FileNameLength/2,tmp,99,NULL,NULL );
          strcpy( str2, tmp );
        }
        obj->DealFun( (ACTION)pNotify->Action, str1, str2 );
      }
      else
      {
        break;
      }
    }
    return 0;
  }
};
以下是测试代码 #include <conio.h>
#include <iostream>
using namespace std;
void __stdcall MyDeal( ACTION act, std::string filename1, std::string filename2 )
{
  switch( act )
  {
  case ADDED:
    cout << "Added  - " << filename1 << endl;
    break;
  case REMOVED:
    cout << "Removed - " << filename1 << endl;
    break;
  case MODIFIED:
    cout << "Modified - " << filename1 << endl;
    break;
  case RENAMED:
    cout << "Rename  - " << filename1 << " " << filename2 << endl;
    break;
  }
}
void main()
{
  FileSystemWatcher a;
  a.Run( "D:\\", MyDeal );
  cout << "Watch D:\\" << endl;
  cout << "Press <q> to quit." << endl;
  while(getch()!='q');
  a.Close();
}

以上代码在 Win2K + VC++6.0 中调试通过,写在同一个文件中是为了调试方便,正式使用时最好能拆分成h文件和cpp文件; 我本想既支持Ansi编码又支持Unicode,但后来心情浮躁,就懒得写了,甚至也没有做足够的测试,所以这段代码写得是很差的,但我实在不想再写了,只想睡觉,所以贴出来抛砖引玉,希望诸位能将修正后的代码贴上来。

Tags:目录 监测

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接