windows 目录监控

转载来源:http://blog.vckbase.com/bruceteen/articles/229.html#Post,作者周星星

因为文章已经在VCKBASE上发表过,故尔这里仅给出链接
http://www.vckbase.com/document/viewdoc.asp?id=814

// 2007-12-14 整理(使用VC2005)

@FileSystemWatcher.hpp

#ifndef __FILESYSTEMWATCHER_HPP__
#define __FILESYSTEMWATCHER_HPP__

#if(_WIN32_WINNT < 0x0400)
#define _WIN32_WINNT 0x0400
#endif
#include <windows.h>

class FileSystemWatcher
{
public:
    enum Filter
    {
        FILTER_FILE_NAME        = 0x00000001, // add/remove/rename
        FILTER_DIR_NAME         = 0x00000002, // add/remove/rename
        FILTER_ATTR_NAME        = 0x00000004,
        FILTER_SIZE_NAME        = 0x00000008,
        FILTER_LAST_WRITE_NAME  = 0x00000010, // timestamp
        FILTER_LAST_ACCESS_NAME = 0x00000020, // timestamp
        FILTER_CREATION_NAME    = 0x00000040, // timestamp
        FILTER_SECURITY_NAME    = 0x00000100
    };
    enum ACTION
    {
        ACTION_ERRSTOP          = -1,
        ACTION_ADDED            = 0x00000001,
        ACTION_REMOVED          = 0x00000002,
        ACTION_MODIFIED         = 0x00000003,
        ACTION_RENAMED_OLD      = 0x00000004,
        ACTION_RENAMED_NEW      = 0x00000005
    };

    typedef void (__stdcall *LPDEALFUNCTION)( ACTION act, LPCWSTR filename, LPVOID lParam );

    FileSystemWatcher();
    ~FileSystemWatcher();

    // LPCTSTR dir: ended-with "//"
    bool Run( LPCTSTR dir, bool bWatchSubtree, DWORD dwNotifyFilter, LPDEALFUNCTION dealfun, LPVOID lParam );
    void Close( DWORD dwMilliseconds=INFINITE );

private: // no-impl
    FileSystemWatcher( const FileSystemWatcher& );
    FileSystemWatcher operator=( const FileSystemWatcher );

private:
    HANDLE m_hDir;
    DWORD m_dwNotifyFilter;
    bool m_bWatchSubtree;
    HANDLE m_hThread;
    volatile bool m_bRequestStop;
    LPDEALFUNCTION m_DealFun;
    LPVOID m_DealFunParam;
    static DWORD WINAPI Routine( LPVOID lParam );
};

#endif // __FILESYSTEMWATCHER_HPP__


@FileSystemWatcher.cpp

#include <cassert>
#include "FileSystemWatcher.hpp"

FileSystemWatcher::FileSystemWatcher() : m_hDir(INVALID_HANDLE_VALUE), m_hThread(NULL)
{
    assert( FILTER_FILE_NAME        == FILE_NOTIFY_CHANGE_FILE_NAME   );
    assert( FILTER_DIR_NAME         == FILE_NOTIFY_CHANGE_DIR_NAME    );
    assert( FILTER_ATTR_NAME        == FILE_NOTIFY_CHANGE_ATTRIBUTES  );
    assert( FILTER_SIZE_NAME        == FILE_NOTIFY_CHANGE_SIZE        );
    assert( FILTER_LAST_WRITE_NAME  == FILE_NOTIFY_CHANGE_LAST_WRITE  );
    assert( FILTER_LAST_ACCESS_NAME == FILE_NOTIFY_CHANGE_LAST_ACCESS );
    assert( FILTER_CREATION_NAME    == FILE_NOTIFY_CHANGE_CREATION    );
    assert( FILTER_SECURITY_NAME    == FILE_NOTIFY_CHANGE_SECURITY    );

    assert( ACTION_ADDED            == FILE_ACTION_ADDED              );
    assert( ACTION_REMOVED          == FILE_ACTION_REMOVED            );
    assert( ACTION_MODIFIED         == FILE_ACTION_MODIFIED           );
    assert( ACTION_RENAMED_OLD      == FILE_ACTION_RENAMED_OLD_NAME   );
    assert( ACTION_RENAMED_NEW      == FILE_ACTION_RENAMED_NEW_NAME   );
}

FileSystemWatcher::~FileSystemWatcher()
{
    Close();
}

bool FileSystemWatcher::Run( LPCTSTR dir, bool bWatchSubtree, DWORD dwNotifyFilter, LPDEALFUNCTION dealfun, LPVOID lParam )
{
    Close();

    m_hDir = CreateFile(
        dir,
        GENERIC_READ,
        FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
        NULL,
        OPEN_EXISTING,
        FILE_FLAG_BACKUP_SEMANTICS,
        NULL
    );
    if( INVALID_HANDLE_VALUE == m_hDir ) return false;

    m_bWatchSubtree = bWatchSubtree;
    m_dwNotifyFilter = dwNotifyFilter;
    m_DealFun = dealfun;
    m_DealFunParam = lParam;
    m_bRequestStop = false;

    DWORD ThreadId;
    m_hThread = CreateThread( NULL,0,Routine,this,0,&ThreadId );
    if( NULL == m_hThread )
    {
        CloseHandle( m_hDir );
        m_hDir = INVALID_HANDLE_VALUE;
    }

    return NULL!=m_hThread;
}

void FileSystemWatcher::Close( DWORD dwMilliseconds )
{
    if( NULL != m_hThread )
    {
        m_bRequestStop = true;
        if( WAIT_TIMEOUT == WaitForSingleObject(m_hThread,dwMilliseconds) )
            TerminateThread( m_hThread, 0 );
        CloseHandle( m_hThread );
        m_hThread = NULL;
    }
    if( INVALID_HANDLE_VALUE != m_hDir )
    {
        CloseHandle( m_hDir );
        m_hDir = INVALID_HANDLE_VALUE;
    }
}

DWORD WINAPI FileSystemWatcher::Routine( LPVOID lParam )
{
    FileSystemWatcher& obj = *(FileSystemWatcher*)lParam;

    BYTE buf[ 2*(sizeof(FILE_NOTIFY_INFORMATION)+2*MAX_PATH)+2 ];
    FILE_NOTIFY_INFORMATION* pNotify=(FILE_NOTIFY_INFORMATION *)buf;
    DWORD BytesReturned;
    while( !obj.m_bRequestStop )
    {
        if( ReadDirectoryChangesW( obj.m_hDir,
            pNotify,
            sizeof(buf)-2,
            obj.m_bWatchSubtree,
            obj.m_dwNotifyFilter,
            &BytesReturned,
            NULL,
            NULL ) ) // 无限等待,应当使用异步方式
        {
            for( FILE_NOTIFY_INFORMATION* p=pNotify; p; )
            {
                WCHAR c = p->FileName[p->FileNameLength/2];
                p->FileName[p->FileNameLength/2] = L'/0';

                obj.m_DealFun( (ACTION)p->Action, p->FileName, obj.m_DealFunParam );

                p->FileName[p->FileNameLength/2] = c;

                if( p->NextEntryOffset )
                    p  = (PFILE_NOTIFY_INFORMATION)( (BYTE*)p + p->NextEntryOffset );
                else
                    p = 0;
            }
        }
        else
        {
            obj.m_DealFun( (ACTION)ACTION_ERRSTOP, 0, obj.m_DealFunParam );
            break;
        }
    }

    return 0;
}


@test.cpp

#include "FileSystemWatcher.hpp"
#include <stdio.h>
#include <locale.h>
#include <assert.h>
#include <tchar.h>
#include <conio.h>

void __stdcall MyDeal( FileSystemWatcher::ACTION act, LPCWSTR filename, LPVOID lParam )
{
    static FileSystemWatcher::ACTION pre = FileSystemWatcher::ACTION_ERRSTOP;
    switch( act )
    {
    case FileSystemWatcher::ACTION_ADDED:
        wprintf_s( L"Added     - %s/n", filename );
        break;
    case FileSystemWatcher::ACTION_REMOVED:
        wprintf_s( L"Removed   - %s/n", filename );
        break;
    case FileSystemWatcher::ACTION_MODIFIED:
        wprintf_s( L"Modified  - %s/n", filename );
        break;
    case FileSystemWatcher::ACTION_RENAMED_OLD:
        wprintf_s( L"Rename(O) - %s/n", filename );
        break;
    case FileSystemWatcher::ACTION_RENAMED_NEW:
        assert( pre == FileSystemWatcher::ACTION_RENAMED_OLD );
        wprintf_s( L"Rename(N) - %s/n", filename );
        break;
    case FileSystemWatcher::ACTION_ERRSTOP:
    default:
        wprintf_s( L"---ERROR---%s/n", filename );
        break;
    }
    pre = act;
}

int main()
{
    LPCTSTR sDir= TEXT("F://temp//cpp06//test//");
    DWORD dwNotifyFilter = FileSystemWatcher::FILTER_FILE_NAME|FileSystemWatcher::FILTER_DIR_NAME;

    FileSystemWatcher fsw;
    bool r = fsw.Run( sDir, true, dwNotifyFilter, &MyDeal, 0 );
    if( !r ) return -1;

    _tsetlocale( LC_CTYPE, TEXT("chs") );
    _tprintf_s( TEXT("Watch%s/n"), sDir );
    _tprintf_s( TEXT("Press <q> to quit./n") );

    while( _getch() != 'q' );

    fsw.Close();

    return 0;
}

用于完成指定目录变化监控 /*----------------------线程函数------------------------------------*/ DWORD WINAPI CDDlg::ThreadProc( LPVOID lParam ) //线程函数 { CDDlg* obj = (CDDlg*)lParam; //参数转化 obj->hDir = CreateFile( //打开目录,得到目录的句柄 obj->m_strWatchedDir, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL ); if(obj->hDir ==INVALID_HANDLE_VALUE ) return false; char buf[(sizeof(FILE_NOTIFY_INFORMATION)+MAX_PATH)*2]; FILE_NOTIFY_INFORMATION* pNotify=(FILE_NOTIFY_INFORMATION*)buf; DWORD dwBytesReturned; 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, &dwBytesReturned, NULL, NULL ) ) { char tmp[MAX_PATH], str1[MAX_PATH], str2[MAX_PATH]; memset( tmp, 0, sizeof(tmp) ); //ZeroMemory() WideCharToMultiByte( CP_ACP,0,pNotify->FileName,pNotify->FileNameLength/2,tmp,99,NULL,NULL ); strcpy( str1, tmp ); if(pNotify->NextEntryOffset !=0 ) { 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 ); } switch(pNotify->Action) { case FILE_ACTION_ADDED: if(obj->m_bAddNew0) { CTime tt=CTime::GetCurrentTime(); CString strTT; strTT.Format("%d:%d:%d",tt.GetHour(),tt.GetMinute(),tt.GetSecond()); obj->m_list.InsertItem(0,obj->m_szi); obj->m_list.SetItemText(0,2,"添加了新文件"); obj->m_list.SetItemText(0,3,str1); obj->m_list.SetItemText(0,1,strTT); // PlaySound(MAKEINTRESOURCE(IDR_WAVE1),AfxGetResourceHandle(),SND_RESOURCE|SND_PURGE|SND_NODEFAULT); } break; case FILE_ACTION_REMOVED: if(obj->m_bDel0) { CTime tt=CTime::GetCurrentTime(); CString strTT; strTT.Format("%d:%d:%d",tt.GetHour(),tt.GetMinute(),tt.GetSecond()); obj->m_list.InsertItem(0,obj->m_szi); obj->m_list.SetItemText(0,2,"删除了文件"); obj->m_list.SetItemText(0,3,str1); obj->m_list.SetItemText(0,1,strTT); // PlaySound(MAKEINTRESOURCE(IDR_WAVE1),AfxGetResourceHandle(),SND_RESOURCE|SND_PURGE|SND_NODEFAULT); } break; case FILE_ACTION_RENAMED_NEW_NAME: if(obj->m_bRename0) { CTime tt=CTime::GetCurrentTime(); CString strTT; strTT.Format("%d:%d:%d",tt.GetHour(),tt.GetMinute(),tt.GetSecond()); obj->m_list.InsertItem(0,obj->m_szi); obj->m_list.SetItemText(0,2,"重命名了文件"); strcat(str1,"->"); obj->m_list.SetItemText(0,3,strcat(str1,str2)); obj->m_list.SetItemText(0,1,strTT); // PlaySound(MAKEINTRESOURCE(IDR_WAVE1),AfxGetResourceHandle(),SND_RESOURCE|SND_PURGE|SND_NODEFAULT); } break; case FILE_ACTION_RENAMED_OLD_NAME: if(obj->m_bRename0) { CTime tt=CTime::GetCurrentTime(); CString strTT; strTT.Format("%d:%d:%d",tt.GetHour(),tt.GetMinute(),tt.GetSecond()); obj->m_list.InsertItem(0,obj->m_szi); obj->m_list.SetItemText(0,2,"重命名了文件"); strcat(str1," 改名为 "); obj->m_list.SetItemText(0,3,strcat(str1,str2)); obj->m_list.SetItemText(0,1,strTT); // PlaySound(MAKEINTRESOURCE(IDR_WAVE1),AfxGetResourceHandle(),SND_RESOURCE|SND_PURGE|SND_NODEFAULT); } break; case FILE_ACTION_MODIFIED: if(obj->m_bModify0) { CTime tt=CTime::GetCurrentTime(); CString strTT; strTT.Format("%d:%d:%d",tt.GetHour(),tt.GetMinute(),tt.GetSecond()); obj->m_list.InsertItem(0,obj->m_szi); obj->m_list.SetItemText(0,2,"修改了文件"); obj->m_list.SetItemText(0,3,str1); obj->m_list.SetItemText(0,1,strTT); // PlaySound(MAKEINTRESOURCE(IDR_WAVE1),AfxGetResourceHandle(),SND_RESOURCE|SND_PURGE|SND_NODEFAULT); } break; default: if(obj->m_bOther0) { CTime tt=CTime::GetCurrentTime(); CString strTT; strTT.Format("%d:%d:%d",tt.GetHour(),tt.GetMinute(),tt.GetSecond()); obj->m_list.InsertItem(0,obj->m_szi); obj->m_list.SetItemText(0,2,"未知变化"); obj->m_list.SetItemText(0,3,""); obj->m_list.SetItemText(0,1,strTT); // PlaySound(MAKEINTRESOURCE(IDR_WAVE1),AfxGetResourceHandle(),SND_RESOURCE|SND_PURGE|SND_NODEFAULT); } break; } obj->m_i++; itoa(obj->m_i,obj->m_szi,10); //AfxBeginThread(SoundThread,0); } else break; } return 0; }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值