//ThreadParameter结构体的定义
 /*
 *整合参数为一个结构体传给子线程的原因在于创建线程时
 *指定的线程入口函数只接受一个LPVOID类型的指针,具体内容可以参考msdn,
 *实际上向子线程传递参数还有一种方法,全局变量,
 *例如后面程序中的WriteLog就是一个文件输入流对象,我就是在程序首部定义的全局变量。
 */
 typedef struct ThreadParameter
 {
     LPTSTR in_directory;//监控的路径
     FILE_NOTIFY_INFORMATION *in_out_notification;//存储监控函数返回信息地址
     DWORD in_MemorySize;//传递存储返回信息的内存的字节数
     DWORD *in_out_BytesReturned;//存储监控函数返回信息的字节数
     DWORD *in_out_version;//返回版本信息
     FILE_NOTIFY_INFORMATION *temp_notification;//备用的一个参数
 }ThreadParameter; void HexDump(char *buf, int len, int addr);
//  函数: WatchChanges(LPVOID lpParameter)
 //
 //  目的: 监控目录的程序
 //
 //  注释:主函数创建线程时制定了这个函数的入口
 //         届时该子程序将自动启动执行。
 //  备注:因为代码不全,看下面的代码时,主要参考红色的字体部分char * testbuff = "12345";
DWORD WINAPI WatchChanges(LPVOID lpParameter)//返回版本信息
 {      
     ThreadParameter *parameter = (ThreadParameter*)lpParameter;
     LPCTSTR WatchDirectory = parameter->in_directory;
       
     TRACE("testbuff len = %d\n", strlen(testbuff)); 
     //创建一个目录句柄
     HANDLE handle_directory = CreateFile( WatchDirectory,
         FILE_LIST_DIRECTORY,
         FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
         NULL,
         OPEN_EXISTING,
         FILE_FLAG_BACKUP_SEMANTICS,
         NULL);
     if (handle_directory == INVALID_HANDLE_VALUE){
         DWORD ERROR_DIR = GetLastError();
         MessageBox(NULL, TEXT("打开目录错误!"), TEXT("文件监控"), 0);
     }
BOOL watch_state;
     int edit_flag;
     edit_flag = 0x00;
     //time_t ChangeTime;
     char file_name[1024];
     PFILE_NOTIFY_INFORMATION p_notify_information;
     //HexDump((char *)parameter->in_out_notification, 0x200, 0);
     
     while (TRUE){
         watch_state = ReadDirectoryChangesW(handle_directory,
             (LPVOID)parameter->in_out_notification,
             parameter->in_MemorySize,
             TRUE,
             FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_LAST_WRITE,
             (LPDWORD)parameter->in_out_BytesReturned,
             NULL,
             NULL);
         TRACE("watch_state = %d\n", watch_state);
         TRACE("watch_state123 = %d\n", *parameter->in_out_BytesReturned);
         //检测结果为1,表明函数已成功执行
         //time(&ChangeTime);
         //记录修改时间
         //TRACE(_T("文件监控,删除文件! %S\\%S\n"), file_name, file_name);
         p_notify_information = parameter->in_out_notification;
         HexDump((char *)p_notify_information, *parameter->in_out_BytesReturned, 0);
         if (GetLastError() == ERROR_INVALID_FUNCTION){
             MessageBox(NULL, TEXT("系统不支持!"), TEXT("文件监控"), 0);
         }else if (watch_state == 0){
             MessageBox(NULL, TEXT("监控失败!"), TEXT("文件监控"), 0);
         }else if (GetLastError() == ERROR_NOTIFY_ENUM_DIR){
             MessageBox(NULL, TEXT("内存溢出!"), TEXT("文件监控"), 0);
         }else{
             //将宽字符类型的FileName变量转换成string,便于写入log文件,否则写不进去正确的文件名
             //string file_name;
             //DWORD length = WideCharToMultiByte(0, 0, parameter->in_out_notification->FileName, -1, NULL, 0, NULL, NULL);
             next_frame:
             DWORD length;
             length = p_notify_information->FileNameLength / 2;
             PSTR ps = new CHAR[length+1];
             ps[length] = '\0';            //TRACE("length = %d\n", length);
             //TRACE("parameter->in_out_notification->FileNameLength = %d\n", p_notify_information->FileNameLength);
             //HexDump((char *)p_notify_information, 0x100, 0);
             if( length >= 0 ){
                 WideCharToMultiByte(0, 0, p_notify_information->FileName, -1, ps, length, NULL, NULL);
                 //HexDump((char *)ps, 0x100, 0);
                 strcpy(file_name, ps);
                 //TRACE("file_name1 = %s\n", file_name);
                 //TRACE("file_name2 len = %d\n", strlen(file_name) );
                 delete[] ps;
             }
             
             //这里主要就是检测返回的信息,需要注意FILE_NOTIFY_INFORMATION结构体的定义,以便正确调用返回信息
             if( p_notify_information->Action == FILE_ACTION_ADDED ){
                 TRACE(_T("文件监控,新增文件: %S\n"), file_name );
             }else if (p_notify_information->Action == FILE_ACTION_REMOVED){
                 TRACE(_T("文件监控,删除文件: %S\n"), file_name );
             }else if (p_notify_information->Action == FILE_ACTION_MODIFIED){
                 TRACE(_T("文件监控,修改文件: %S\n"), file_name );
             }else if( p_notify_information->Action == FILE_ACTION_RENAMED_OLD_NAME ){           
                 TRACE(_T("文件监控,重命名->老名字: %S\n"), file_name );
             }else if( p_notify_information->Action == FILE_ACTION_RENAMED_NEW_NAME ){
                 TRACE(_T("文件监控,重命名->新名字: %S\n"), file_name );
             }
             if( p_notify_information->NextEntryOffset ){
                 p_notify_information = PFILE_NOTIFY_INFORMATION((int)p_notify_information + p_notify_information->NextEntryOffset);
                 goto next_frame;
             }else{
                 memset(parameter->in_out_notification, '\0', 1024);
             }
         }
         Sleep(100);
     }
     return 0;
 }//传递给WatchChanges函数的参数,这部分代码截自主函数
 char notify[1024];FILE_NOTIFY_INFORMATION *Notification = (FILE_NOTIFY_INFORMATION *)notify;
 FILE_NOTIFY_INFORMATION *TempNotification = NULL;
 DWORD BytesReturned = 0;
 DWORD version = 0;LPTSTR  Directory = L"F:\\A50\\java\\doip\\uart\\libs\\armeabi\\";
//整合传给子线程的参数,该结构体的定义参考上面的定义
 ThreadParameter ParameterToThread = { Directory, Notification, sizeof(notify), &BytesReturned, &version, TempNotification };void Cfile_extractDlg::OnBnClickedCheck2()
 {
     // TODO:  在此添加控件通知处理程序代码
     CButton* pBtn = (CButton*)GetDlgItem(IDC_CHECK2);
     int state = pBtn->GetCheck();
     if (state == 1){
         g_current_file_modify_monitor_enable = 0x01;
     }
     else{
         g_current_file_modify_monitor_enable = 0x00;        //::AfxBeginThread( Monitor, (LPVOID)m_hWnd );
         memset(notify, '\0', 1024);
         
                  
        //创建一个线程专门用于监控文件变化
         HANDLE TrheadWatch = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)WatchChanges, &ParameterToThread, 0, NULL);
         CloseHandle(TrheadWatch);    }
}


 

 

 

这种模式有一个缺点,就是线程没法主动退出来

只有文件变化了 才能解除 ReadDirectoryChangesW函数的阻塞

做不到 主动、灵活可控的线程控制

也就是cpu资源不能随意控制

不爽

不过基本功能已经实现了 不会丢失文件的变化信息