Chinaunix首页 | 论坛 | 博客
  • 博客访问: 9727008
  • 博文数量: 1227
  • 博客积分: 10026
  • 博客等级: 上将
  • 技术积分: 20273
  • 用 户 组: 普通用户
  • 注册时间: 2008-01-16 12:40
文章分类

全部博文(1227)

文章存档

2010年(1)

2008年(1226)

我的朋友

分类: C/C++

2008-03-14 14:11:14

下载本文示例代码

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

问题:

原程序中在处理多个文件拷贝和山删除时不能完全显示,如对200个文件进行拷贝:
copy temp\*.txt
仅能监控到3个文件变化,目前发现拷贝时对同一个文件有5个 FILE_ACTION_ADDED 显示
( 测试环境: Microsoft Windows 2000 [Version 5.00.2195] )

一、对FileSystemWatcher.h 的改进:

#define _WIN32_WINNT 0x0500

#include 
#include 
#include 

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 
#include 
#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  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;
}

(全文完)
下载本文示例代码
阅读(1930) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~