Obtaining Directory Change Notifications

本文介绍使用Win32 API实现文件和目录变更通知的方法,包括使用FindFirstChangeNotification、FindNextChangeNotification和ReadDirectoryChangesW函数监测指定目录及其子目录的变更。通过创建线程并等待变更通知,然后比较新旧目录状态来获取具体变更。

Obtaining Directory Change Notifications

 

About APIs, you can go to this link: http://msdn.microsoft.com/en-us/library/aa365261(VS.85).aspx

 

Note following items extracted from MSDN:

1.     The wait functions can monitor the specified directory or subtree by using the handle returned by the FindFirstChangeNotification function. A wait is satisfied when one of the filter conditions occurs in the monitored directory or subtree.

2.     After the wait has been satisfied, the application can respond to this condition and continue monitoring the directory by calling the FindNextChangeNotification function and the appropriate wait function. When the handle is no longer needed, it can be closed by using the FindCloseChangeNotification function.

3.     This function does not indicate the change that satisfied the wait condition. To retrieve information about the specific change as part of the notification, use the ReadDirectoryChangesW function.

 

To read the changes, we can use a WIN32_FIND_DATA list to keep the old attributes of the directory.

1.       Adding the specified folder to monitor queue

void CFileMonitor::Add(const _bstr_t &file)

{

      CFileMonitor *pThis = new CFileMonitor(file);

     

      //Reading files in the directory

      pThis->RefreshDirectory(FALSE);

 

      pThis->SetChange(::FindFirstChangeNotification(

                           path,

                           FALSE,  

                           FILE_NOTIFY_CHANGE_FILE_NAME |                    FILE_NOTIFY_CHANGE_LAST_WRITE

                          ));

 

      if (pThis->GetChange() == INVALID_HANDLE_VALUE)

      {

            delete pThis;

            return;

      }

 

      DWORD ThreadId;

      HANDLE ht = ::CreateThread(

            NULL,

            0,                                                      CFileMonitor::ThreadAdd,

            pThis,                                   

            0,                                       

            &ThreadId);                        

 

 

      if (ht == NULL)

            delete pThis;

 

      else

            ::CloseHandle(ht);

}

 

 

 

 

 

2.       In thread Add, wait and capture the change notification

DWORD WINAPI CFileMonitor::ThreadAdd(LPVOID lpParameter)

{

      CFileMonitor *pThis = (CFileMonitor *)lpParameter;

 

      DWORD rc;

      do

      {

            //TODO: I should have a timeout value

            rc = ::WaitForSingleObject(pThis->GetChange(), INFINITE);

 

            // take new snap shot of directory and get notification of changes

            pThis->RefreshDirectory();

      } while(!pThis->IsAdded() && rc == WAIT_OBJECT_0);

 

      // cleanup

      delete pThis;

 

      return 0;

}

 

 

3.       Compare the items

void CFileMonitor::RefreshDirectory(BOOL bNotify /* default is TRUE */)

{

      if (m_path.length() == 0)

            return;

 

      // find all the files that match the path spec

      int count = 0;

      WIN32_FIND_DATA *pFindArray = NULL;

      WIN32_FIND_DATA FindFileData;

      HANDLE hFind = ::FindFirstFile(m_path, &FindFileData);

      BOOL more = hFind != INVALID_HANDLE_VALUE;

      while(more)

      {

            if ((FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) // skip directories

            {

                  // allocate a new entry in this snap shot (pFinDArray)

                  count++;

                  pFindArray = (WIN32_FIND_DATA *)realloc(pFindArray, count * sizeof(*pFindArray));

 

                  // add this file to the new snap shot

            memcpy(pFindArray + count - 1, &FindFileData, sizeof(*pFindArray));

 

                  if (bNotify)

                  {

                        DWORD fcs = GetFileStatus(m_pFindArray, m_count, FindFileData);

                  if (fcs != FILE_CHANGE_NONE)

                        OnFileChange(FindFileData, fcs);

                  }

            }

 

            more = ::FindNextFile(hFind, &FindFileData);

    }

 

      if (m_pFindArray)

            free(m_pFindArray);

 

      m_pFindArray = pFindArray;

      m_count = count;

}

 

 

 

 

 

 

 

转载于:https://www.cnblogs.com/pangpangxiong/archive/2009/09/08/1562630.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值