2012年(158)
分类: C/C++
2012-11-14 16:11:37
因为文章已经在上发表过,故尔这里仅给出链接
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
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
#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
#include
#include
#include
#include
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 to quit.\n")
);
while( _getch() != 'q' );
fsw.Close();
return 0;
}