• 文件监控——ReadDirecotryChangesW


    实现原理:

      实现文件监控操作的核心函数是ReadDirecotryChangesW。这个API函数可以设置监控目录、过滤条件,从而获取监控数据。在调用API函数ReadDirecotryChangesW设置监控过滤条件之前,需要先通过CreateFile函数打开监控目录,获取监控目录的句柄。之后才能调用ReadDirecotryChangesW函数设置监控过滤条件并阻塞,直到有满足监控过滤条件的操作,ReadDirecotryChangesW才会返回监控数据继续往下执行。接下来便根据返回的监控数据,判断操作类型以及获取相关数据。

      注意:调用一次ReadDirectoryChangesW函数,只会监控一次。要想实现持续监控,则需要程序循环调用ReadDirectoryChangesW函数来设置监控并获取监控数据。由于持续的目录监控需要不停循环调用ReadDirecotryChangesW函数进行设置监控和获取监控数据,所以,如果把这段代码放在主线程中,则可能会导致程序阻塞。为了解决主线程阻塞的问题,可以创建一个文件监控子线程,把文件监控的实现代码放到子线程中运行

    实现过程:

      (1).打开目录,获取文件句柄(必须要用FILE_LIST_DIRECTORY 权限与FILE_FLAG_BACKUP_SEMANTICS标志)

      (2).设置目录监控

      (3).判断文件操作类型

    实现代码:

    //开启监控按钮
    void CFileMonitDlg::OnBnClickedButton1()
    {
        // TODO: 在此添加控件通知处理程序代码
    
        UpdateData(TRUE);
    
        //检测文件是否存在
        if (GetFileAttributes(m_Edit_Path) == INVALID_FILE_ATTRIBUTES)
        {
            MessageBox(_T("文件不存在 请重试!"));
            return;
        }
    
        USES_CONVERSION;
        //创建线程
        CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)MonitorFileThreadProc, this, 0, NULL);
    
        return;
    }
    
    
    // 目录监控多线程
    UINT MonitorFileThreadProc(LPVOID lpVoid)
    {
        CFileMonitDlg* ptrData = (CFileMonitDlg*)lpVoid;
        CString temp;
        temp = ptrData->m_Edit_Path + L"\";
    
        // 打开目录, 获取文件句柄
        HANDLE hDirectory = ::CreateFile(temp.GetBuffer(), FILE_LIST_DIRECTORY,
            FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
            FILE_FLAG_BACKUP_SEMANTICS, NULL);
        if (INVALID_HANDLE_VALUE == hDirectory)
        {
    
            MessageBoxA(0, "CreateFileA Error", "Error", MB_OK);
            return 1;
        }
    
        DWORD dwBufferSize = 4096;
        // 申请一个足够大的缓冲区 
        BYTE* pBuf = new BYTE[dwBufferSize];
        if (NULL == pBuf)
        {
            MessageBoxA(0, "new Error", "Error", MB_OK);
            return 2;
        }
    
        FILE_NOTIFY_INFORMATION* pFileNotifyInfo = (FILE_NOTIFY_INFORMATION *)pBuf;
        
        BOOL bRet = FALSE;
        DWORD dwRet = 0;
        CString res = L"";
        // 开始循环设置监控
        do
        {
            ::RtlZeroMemory(pFileNotifyInfo, dwBufferSize);
            // 设置监控目录
            bRet = ::ReadDirectoryChangesW(hDirectory,
                pFileNotifyInfo,
                dwBufferSize,
                TRUE,
                FILE_NOTIFY_CHANGE_FILE_NAME |
                FILE_NOTIFY_CHANGE_ATTRIBUTES |
                FILE_NOTIFY_CHANGE_LAST_WRITE,
                &dwRet,
                NULL, NULL);
            if (FALSE == bRet)
            {
                MessageBoxA(0, "ReadDirectoryChangesW Error", "Error", MB_OK);
                break;
            }
    
            // 判断操作类型并显示
            switch (pFileNotifyInfo->Action)
            {
                //新增文件
            case FILE_ACTION_ADDED:
            {
                temp.Format(_T("%s:%s
    "), _T("新增文件"), pFileNotifyInfo->FileName);
                res += temp + L"
    ";
                break;
            }
                //删除文件
            case FILE_ACTION_REMOVED:
            {
                temp.Format(_T("%s:%s
    "), _T("删除文件"), pFileNotifyInfo->FileName);
                res += temp + L"
    ";
                break;
            }
                //修改文件
            case FILE_ACTION_MODIFIED:
            {
                temp.Format(_T("%s:%s
    "), _T("修改文件"), pFileNotifyInfo->FileName);
                res += temp + L"
    ";
                break;
            }
                //重命名文件
            case FILE_ACTION_RENAMED_OLD_NAME:
            {
                temp.Format(_T("%s:%s
    "), _T("重命名前文件"), pFileNotifyInfo->FileName);
                res += temp + L"
    ";
                break;
            }
            case FILE_ACTION_RENAMED_NEW_NAME:
            {
                temp.Format(_T("%s:%s
    "), _T("重命名后文件"), pFileNotifyInfo->FileName);
                res += temp + L"
    ";
                break;
            }
            default:
                break;
            }
    
            SetDlgItemText(ptrData->m_hWnd,IDC_EDIT2, res);
    
        } while (bRet);
    
    
    
        // 关闭句柄, 释放内存
        CloseHandle(hDirectory);
        delete[] pBuf;
    
        return 0;
    }
  • 相关阅读:
    【两周一本书】大话设计模式
    如何将在AWS上的网站快速从http转换为https
    java中error和exception的区别
    Java IO : NIO与IO的区别
    TCP/TP:DNS区域(Zone)
    Liferay 7:Liferay DXP解决方案
    Eclipse:Eclipse插件开发全套教程
    Liferay 7:Liferay DXP全套教程内附源码
    Liferay 7:Liferay内部博客地址
    Gradle:gradle下载插件
  • 原文地址:https://www.cnblogs.com/ndyxb/p/12913790.html
Copyright © 2020-2023  润新知