Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1367551
  • 博文数量: 946
  • 博客积分: 52360
  • 博客等级: 大将
  • 技术积分: 13080
  • 用 户 组: 普通用户
  • 注册时间: 2008-08-07 17:31
文章分类

全部博文(946)

文章存档

2011年(1)

2008年(945)

我的朋友

分类: C/C++

2008-08-07 17:37:39

下载本文示例代码
测试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;

}



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