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

目录监测的讨论

 2006-07-20 11:39:07 来源:WEB开发网   
核心提示:测试VC知识库中周星星所写的《目录监测》一文所提供的程序,发现有一些不够完善的地方,遂写出与大家共同探讨,目录监测的讨论,问题:原程序中在处理多个文件拷贝和山删除时不能完全显示,如对200个文件进行拷贝:copy temp\*.txt仅能监控到3个文件变化,目前发现拷贝时对同一个文件有5个 FILE_ACTION_AD

测试VC知识库中周星星所写的《目录监测》一文所提供的程序,发现有一些不够完善的地方,遂写出与大家共同探讨。

问题:

原程序中在处理多个文件拷贝和山删除时不能完全显示,如对200个文件进行拷贝:

copy temp\*.txt

仅能监控到3个文件变化,目前发现拷贝时对同一个文件有5个 FILE_ACTION_ADDED 显示

( 测试环境: Microsoft Windows 2000 [Version 5.00.2195] )

一、对FileSystemWatcher.h 的改进:

#define _WIN32_WINNT 0x0500
#include <windows.h>
#include <string>
#include <cassert>
void  SendOutNotify(PFILE_NOTIFY_INFORMATION f_pNotify);
#define DeFileWaterBuffer (1000* (sizeof(FILE_NOTIFY_INFORMATION)+MAX_PATH) )
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 );
    hThread=CreateThread( NULL,0,RoutineTest,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
    );
    */
    //hcs change
    obj->hDir = CreateFile(
     obj->WatchedDir.c_str(),              // pointer to the file name
     FILE_LIST_DIRECTORY,        // access (read/write) mode
     FILE_SHARE_READ|FILE_SHARE_DELETE, // share mode
     NULL,                // security descriptor
     OPEN_EXISTING,           // how to create
     FILE_FLAG_BACKUP_SEMANTICS,     // file attributes
     NULL                // file with attributes to copy
                );
    if( INVALID_HANDLE_VALUE == obj->hDir ) return false;
    char buf[ 50*(sizeof(FILE_NOTIFY_INFORMATION)+MAX_PATH) ];
    FILE_NOTIFY_INFORMATION* pNotify=(FILE_NOTIFY_INFORMATION *)buf;
    DWORD BytesReturned;
    while(true)
    {
      memset(buf,0,sizeof(buf));
      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 );
        */
        SendOutNotify(pNotify);
      }
      else
      {
        break;
      }
    }
    return 0;
  }
  static DWORD WINAPI RoutineTest( LPVOID lParam )
  {
    FileSystemWatcher* obj = (FileSystemWatcher*)lParam;
    //hcs change
    obj->hDir = CreateFile(
     obj->WatchedDir.c_str(),      // pointer to the file name
     FILE_LIST_DIRECTORY,        // access (read/write) mode
     FILE_SHARE_READ|FILE_SHARE_DELETE, // share mode
     NULL,                // security descriptor
     OPEN_EXISTING,           // how to create
     FILE_FLAG_BACKUP_SEMANTICS,     // file attributes
     NULL                // file with attributes to copy
                );
    if( INVALID_HANDLE_VALUE == obj->hDir ) return false;
    char *pcBufferNs=new char[DeFileWaterBuffer];
    FILE_NOTIFY_INFORMATION* pNotify=(FILE_NOTIFY_INFORMATION *)pcBufferNs;
    DWORD BytesReturned;
    while(true)
    {
      memset(pcBufferNs,0,DeFileWaterBuffer);
      BytesReturned=0;
      if(
        ReadDirectoryChangesW(
        obj->hDir,
        pNotify,
        DeFileWaterBuffer,
        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 );
        */
        if(BytesReturned> 0)
        {
         SendOutNotify(pNotify);
        }
        else
        {
         //AfxMessageBox("Buffer is small");
         MessageBox(0,"Buffer is small","error",MB_OK);
        }
      }
      else
      {
        break;
      }
    }
    delete [] pcBufferNs;
    return 0;
  }
};
二、对FileSystemWatcher.cpp 的改进: #include "stdafx.h"
#include <conio.h>
#include <iostream>
#include "FileSystemWatcher.h"
using namespace std;
static int g_nChangeTimes;
void __stdcall MyDeal( ACTION act, std::string filename1, std::string filename2 )
{
  g_nChangeTimes++;
  
  /*
  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;
  a.Run( "C:\\", MyDeal );
  cout << "Watch C:\\" << endl;
  cout << "Press <q> to quit." << endl;
  while(getch()!=''q'');
  a.Close();
}
//hcs add use for test file change
void  SendOutNotify(PFILE_NOTIFY_INFORMATION f_pNotify)
{
  PFILE_NOTIFY_INFORMATION pNextNotify=f_pNotify ;
  char pcfilename[MAX_PATH];
  for(int i=0;i<5000;i++)
  {
   g_nChangeTimes++;
   memset(pcfilename , 0, MAX_PATH );
   WideCharToMultiByte( CP_ACP,0,pNextNotify->FileName,pNextNotify->FileNameLength/2,pcfilename,MAX_PATH,NULL,NULL );
   //*(pcfilename+f_pNotify->FileNameLength)=0;
   switch( f_pNotify->Action )
   {
     case FILE_ACTION_ADDED:
         cout << "Added  - " << pcfilename << endl;
         break;
     case FILE_ACTION_REMOVED:
         cout << "Removed - " << pcfilename << endl;
         break;
     case FILE_ACTION_MODIFIED:
         cout << "Modified - " << pcfilename << endl;
         break;
     case FILE_ACTION_RENAMED_OLD_NAME:
         cout << "Rename  - " << pcfilename << " " << "filename2" << endl;
         break;
     case FILE_ACTION_RENAMED_NEW_NAME:
         cout << "RenameNew  - " << pcfilename << " " << "filename2" << endl;
         break;
   }
   cout << "Message Times is" << i << " File Len is "<< g_nChangeTimes << endl;;
   //pNextNotify->FileNameLength << endl;
   if(pNextNotify->NextEntryOffset)
   {
    pNextNotify=(PFILE_NOTIFY_INFORMATION)((char*)pNextNotify+pNextNotify->NextEntryOffset);
   }
   else
   {
    break;
   }
  }
  return;
}

Tags:目录 监测 讨论

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