Obtaining Directory Change Notifications

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;

}

 

 

 

 

 

 

 

posted @ 2009-09-08 16:16  Pang pang Xiong  阅读(271)  评论(0编辑  收藏  举报