监控文件的变化 (同步模式)

//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资源不能随意控制

不爽

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值