My FAQ,最新最全的IT技术教程
最新100篇 | 推荐100篇 | 专题100篇 | 排行榜 | 搜索 | 在线API文档
首 页 | 程序开发 | 操作系统 | 软件应用 | 图形图象 | 网络应用 | 精文荟萃 | 教育认证 | 硬件维护 | 未整理篇 | 站长教程
ASP JS PHP工程 ASP.NET 网站建设 UML J2EESUN .NET VC VB VFP 网络维护 数据库 DB2 SQL2000 Oracle Mysql
服务器 Win2000 Office C DreamWeaver FireWorks Flash PhotoShop 上网宝典 CorelDraw 协议大全 网络安全 微软认证
硬件维护  CPU  主板  硬盘  内存  显卡  显示器  键盘鼠标  声卡音箱  打印机  机箱电源  BIOS  网卡  C#  Java  Delphi  vs.net2005
  当前位置:> 程序开发 > 编程语言 > Visual C++ > 系统
目录监测
作者:未知 时间:2005-07-20 14:20 出处:VC知识库 责编:MyFAQ
              摘要:目录监测
目录监测
作者:周星星

下载本文示例工程

   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,但后来心情浮躁,就懒得写了,甚至也没有做足够的测试,所以这段代码写得是很差的,但我实在不想再写了,只想睡觉,所以贴出来抛砖引玉,希望诸位能将修正后的代码贴上来。

关闭本页
 
首页 | 投资与合作 | 服务条款 | 隐私政策 | 收藏本站 | 设为首页 | 新用户注册 | 免责声明 | 使用帮助
Copyright ©2005-2008 myfaq.com.cn All rights reserved. www.myfaq.com.cn 版权所有