C++监测文件夹变化

转自:http://blog.csdn.net/zhihu008/article/details/7995829

Barry注:只是学习ReadDirectoryChangesW的时候发现的一个例子,用于理解ReadDirectoryChangesW的用法,目前发现的不足之处有:

1. ReadDirectoryChangesW的退出不优雅,直接TerminateThread实属下下策,如果close时无限等待,很容易死锁

2. 监控目录不为空时,直接删除见空目录,ReadDirectoryChangesW也不会感知到,线程不会退出,除非手动再次start(会死锁,因为start中的close是无限等待)

FileSystemWatcher.h

#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: dont end-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 "FileSystemWatcher.h"
#include <cassert>

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目录不能以'\'结尾,否则监测不到dir目录被删除,不以\结尾,可以检测到(仅限于空目录时)
  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;
}

main函数

#include "stdafx.h"
#include "FileSystemWatcher.h"
#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("D:\\监测文件夹");
 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(1000);

 return 0;
}




  • 0
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 如何监测文件的变化并自动发送邮件呢?我们可以借助一些工具来实现这一功能。 首先,我们需要选择一个能够监测文件变化的工具。在Windows操作系统中,我们可以使用PowerShell命令或者使用第三方工具实现,如FreeFileSync或Karen's Replicator等。在Linux系统下,我们可以使用inotify工具。 接下来,我们需要配置邮件服务器信息以及发送邮件的脚本。在配置好邮件服务器信息之后,我们可以通过PowerShell命令或者Python脚本来实现自动发送邮件。 在设置监测文件并自动发送邮件之前,我们需要考虑一些注意事项。例如,在选择监测文件的时候要确保该文件经常发生变化,同时要选择监测文件的合适时间间隔。此外,在设置邮件发送脚本的时候,要确保邮件的安全性,比如使用SSL或TLS加密协议等。 总之,通过选择合适的监测文件工具、设置邮件服务器信息、编写自动发送邮件的脚本等步骤,我们可以轻松实现监测文件变化并自动发送邮件的功能,为我们的工作提供更多的便利。 ### 回答2: 监测文件变化自动发送邮件是一种非常方便的方法,可以实时地监测文件的修改情况,保证文件的安全性,避免误操作和丢失。 为了实现这一功能,我们可以使用一些常用的工具或者编程语言,如Linux环境下的inotify工具,或Python语言中的Watchdog库。通过简单的配置,这些工具可以自动监测所需文件的变化,如文件的编辑、删除和重命名等操作,并在检测到变化时自动触发指定的操作。 其中,发送邮件是常见的操作之一。我们可以使用SMTP协议连接到指定的邮件服务器,发送邮件到指定的邮箱,同时在邮件正文中添加所需的内容,如修改详情、变化时间等等,方便我们随时随地了解文件的变化情况。 然而,需要注意的是,在实际应用中,我们还需要考虑一些安全性问题,如邮件的加密传输、权限的控制等等,以确保数据的安全性和保密性。 总之,监测文件变化自动发送邮件是一项非常实用的功能,不仅可以提高工作效率和数据的安全性,还能为IT工作者带来更好的工作体验。 ### 回答3: 在软件开发和信息技术行业中,经常需要对代码和文件进行监测,以确保它们在被修改和更新后能够正常运行。对于程序员和系统管理员来说,能够及时了解这些变化非常重要,因此监测文件变化自动发送邮件的功能非常有用。 为实现此功能,可以使用一些第三方工具,如:inotify-tools, md5sum等。 这些工具可以通过监测文件系统的事件,来检测到文件的变化。当系统检测到文件有修改,就会执行一个shell脚本,脚本会通过邮件客户端接口来发送邮件通知。邮件内容通常包括被修改文件的详细信息,如文件名、路径、时间戳和修改者等。 使用此功能可以让开发人员和系统管理员能够及时了解文件的变化,把握系统的变更情况。这个功能可以适用于一些紧急项目,要求及时响应问题的环境中,可以减少疏漏和人为失误,提高工作效率,确保项目进展和数据的安全性。 总之,监测文件变化自动发送邮件是一项非常有用的功能,对于程序员和系统管理员来说都非常实用,可以方便地了解系统的变化情况,提高工作效率和数据的安全性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值