• Windows下文件的监控


    Windows 2000 引入了两个新接口,FindFirstChangeNotification 和 ReadDirectoryChangesW 。 FindFirstChangeNotification 很容易使用,但没有给出变更文件的信息。即便如此,这个函数对某些应用程序还是很有用的,比如传真服务和 SMTP 服务可以通过拖拽一个文件到一个目录来接受任务队列。ReadDirectoryChangesW 会给出变更的内容和方式, 不过相对的,在使用上也更复杂一些。

    1.FindFirstChangeNotification()函数

    功能:创建一个改变通知句柄,并设置通知条件,即发生某种修改时,该通知句柄将被促发生效。该函数仅仅负责对文件修改作出通知,并不记录和反馈修改信息。

    返回值:成功时返回指向改变通知的句柄,失败时返回INVALID_HANDLE_VALUE,可以用GetLastError()函数得到。

    例子:部分代码如下

    //使用FindFirstChangeNotification和FindNextChangeNotification实现文件监控
    CString Monitor1()
    {
    HANDLE hEvent;//监控句柄
    //char* path[MAX_PATH+1] ;//监控目录
    static int m_nCount = 0; //当前操作的序号
    CString str;

    //GetCurrentDirectory(MAX_PATH, (LPWSTR)path);
    hEvent = FindFirstChangeNotification("E:\",TRUE,FILE_NOTIFY_CHANGE_FILE_NAME| //查看指定目录下任何文件名的改变
    FILE_NOTIFY_CHANGE_DIR_NAME| //查看指定目录下任何目录名的改变
    FILE_NOTIFY_CHANGE_SIZE| //查看指定文件大小的改变
    FILE_NOTIFY_CHANGE_ATTRIBUTES);//查看指定目录下文件属性的改变
    if (hEvent == INVALID_HANDLE_VALUE)
    {
    //ExitProcess(GetLastError());//获取错误
    //return;
    str.Format("%s %s", "error", GetLastError());
    return str;
    }
    //while (TRUE)//循环监控
    {
    DWORD nobj;
    nobj= WaitForSingleObject(hEvent,INFINITE);//等待,文件夹任何动作,都返回0,顾不能知道具体动作和具体哪个文件发生了变化
    if (nobj)
    {
    ;
    }
    m_nCount++;
    str.Format("%d %s", m_nCount, "文件发生了变化!");
    printf("文件发生了变化 ");

    //继续监控
    if(FALSE==FindNextChangeNotification(hEvent))
    {
    //ExitProcess(GetLastError());
    //return;
    str.Format("%s %s", "error", GetLastError());
    return str;
    }
    }
    return str;
    }

    2.ReadDirectoryChangesW()函数

    功能:监控文件修改,并记录文件修改的相关信息,如修改的文件名,何种类型的修改等。

    返回值:如果函数成功,返回值就是非0。对于同步调用,这意味着操作成功,对于异步调用,这意味着操作成功地排队。如果函数失败,返回值是0。如果操作目录或文件系统不支持这个操作,函数将返回ERROR_INVALID_FUNCTION,可以使用GetLastError()函数获取。

    例子:部分代码如下

    //使用ReadDirectoryChangesW实现文件监控
    CString Monitor2()
    {
    DWORD cbBytes;
    char cFileName[1024]; //设置文件名
    char cNewFileName[1024]; //设置文件重命名后的名字
    char cNotify[1024];
    static int m_nCount = 0; //当前操作的序号
    TCHAR *pDirectory = "E:\";//m_strAddress.GetBuffer(m_strAddress.GetLength());

    CString str;
    HANDLE dirHandle;
    dirHandle = CreateFile(
    pDirectory,
    GENERIC_READ | GENERIC_WRITE | FILE_LIST_DIRECTORY,
    FILE_SHARE_READ | FILE_SHARE_WRITE,
    NULL,
    OPEN_EXISTING,
    FILE_FLAG_BACKUP_SEMANTICS,
    NULL);

    memset(cNotify, 0, strlen(cNotify));

    FILE_NOTIFY_INFORMATION *pNotify = (FILE_NOTIFY_INFORMATION*)cNotify;

    //若网络重定向或目标文件系统不支持该操作,函数失败,同时调用GetLastError()返回ERROR_INVALID_FUNCTION
    if(dirHandle == INVALID_HANDLE_VALUE)
    {
    str.Format("%s %s", "error", GetLastError());
    return str;
    }

    if(ReadDirectoryChangesW(
    dirHandle,
    &cNotify,
    1024,
    true,
    FILE_NOTIFY_CHANGE_FILE_NAME |
    FILE_NOTIFY_CHANGE_DIR_NAME
    //| FILE_NOTIFY_CHANGE_CREATION
    //| FILE_NOTIFY_CHANGE_LAST_WRITE
    | FILE_NOTIFY_CHANGE_SIZE,
    &cbBytes,NULL,NULL))
    {
    //转换文件名为多字节字符串
    if(pNotify->FileName)
    {
    memset(cFileName, 0, strlen(cFileName));
    WideCharToMultiByte(CP_ACP, 0, pNotify->FileName, pNotify->FileNameLength/2, cFileName, 99, NULL, NULL);
    }

    //获取重命名的文件名
    if(pNotify->NextEntryOffset != 0 && (pNotify->FileNameLength > 0 && pNotify->FileNameLength < MAX_PATH))
    {
    PFILE_NOTIFY_INFORMATION p = (PFILE_NOTIFY_INFORMATION)((char*)pNotify + pNotify->NextEntryOffset);
    memset(cNewFileName, 0, sizeof(cNewFileName));
    WideCharToMultiByte(CP_ACP, 0, p->FileName, p->FileNameLength/2, cNewFileName, 99, NULL, NULL);
    }

    //设置类型过滤器,监听文件创建、更改、删除、重命名等
    switch(pNotify->Action)
    {
    case FILE_ACTION_ADDED:
    m_nCount++;
    str.Format("%d %s %s", m_nCount, "file add:", cFileName);
    //AfxMessageBox(str);
    break;
    case FILE_ACTION_MODIFIED:
    m_nCount++;
    str.Format("%d %s %s", m_nCount, "file modified:", cFileName);
    //AfxMessageBox(str);
    break;
    case FILE_ACTION_REMOVED:
    m_nCount++;
    str.Format("%d %s %s", m_nCount, "file removed:", cFileName);
    //AfxMessageBox(str);
    break;
    case FILE_ACTION_RENAMED_OLD_NAME:
    m_nCount++;
    str.Format("%d %s %s %s %s", m_nCount, "file renamed:", cFileName, "->", cNewFileName);
    //AfxMessageBox(str);
    break;

    default:
    //MessageBox("unknow command!");
    break;
    }
    CloseHandle(dirHandle);
    }
    return str;
    }

  • 相关阅读:
    嵌入式工程师为何不用学习C++语言?
    汽车电子基础知识
    为什么寄存器比存储器快?
    数字信号和模拟信号
    JLink和JTag的区别
    C++中static关键字作用总结
    所谓高情商,就是会说话
    汽车电子缩略语及术语
    卷积
    算法整理
  • 原文地址:https://www.cnblogs.com/zerotoinfinity/p/6387669.html
Copyright © 2020-2023  润新知