Как посмотреть, изменился ли подфайл каталога - PullRequest
7 голосов
/ 11 сентября 2008

В Windows есть простой способ узнать, есть ли в папке подфайл, который изменился?

Я подтвердил, и дата последнего изменения в папке не обновляется при изменении подфайла.

Могу ли я установить запись в реестре, которая изменит это поведение?

Если это имеет значение, я использую том NTFS.

В конечном итоге я хотел бы получить эту возможность из программы на C ++.

Рекурсивное сканирование всего каталога не будет работать для меня, поскольку папка слишком велика.

Обновление: мне действительно нужен способ сделать это без запуска процесса, пока происходит изменение. Поэтому установка наблюдателя файловой системы для меня не оптимальна.

Обновление 2: бит архива также не будет работать, поскольку он имеет ту же проблему, что и дата последнего изменения. Будет установлен бит архива файла, а папки - нет.

Ответы [ 8 ]

6 голосов
/ 11 сентября 2008

Эта статья должна помочь. По сути, вы создаете один или несколько объектов уведомлений, таких как:

HANDLE dwChangeHandles[2]; 
dwChangeHandles[0] = FindFirstChangeNotification( 
      lpDir,                          // directory to watch 
      FALSE,                          // do not watch subtree 
      FILE_NOTIFY_CHANGE_FILE_NAME);  // watch file name changes 

   if (dwChangeHandles[0] == INVALID_HANDLE_VALUE) 
   {
     printf("\n ERROR: FindFirstChangeNotification function failed.\n");
     ExitProcess(GetLastError()); 
   }

// Watch the subtree for directory creation and deletion.  
   dwChangeHandles[1] = FindFirstChangeNotification( 
      lpDrive,                       // directory to watch 
      TRUE,                          // watch the subtree 
      FILE_NOTIFY_CHANGE_DIR_NAME);  // watch dir name changes 

   if (dwChangeHandles[1] == INVALID_HANDLE_VALUE) 
   {
     printf("\n ERROR: FindFirstChangeNotification function failed.\n");
     ExitProcess(GetLastError()); 
   }

и вы ждете уведомления:

 while (TRUE) 
   { 
   // Wait for notification. 
      printf("\nWaiting for notification...\n");

      DWORD dwWaitStatus = WaitForMultipleObjects(2, dwChangeHandles, 
         FALSE, INFINITE); 

      switch (dwWaitStatus) 
      { 
         case WAIT_OBJECT_0: 

         // A file was created, renamed, or deleted in the directory.
         // Restart the notification. 
             if ( FindNextChangeNotification(dwChangeHandles[0]) == FALSE )
             {
               printf("\n ERROR: FindNextChangeNotification function failed.\n");
               ExitProcess(GetLastError()); 
             }
             break; 

         case WAIT_OBJECT_0 + 1: 

         // Restart the notification. 
             if (FindNextChangeNotification(dwChangeHandles[1]) == FALSE )
             {
               printf("\n ERROR: FindNextChangeNotification function failed.\n");
               ExitProcess(GetLastError()); 
             }
             break; 

         case WAIT_TIMEOUT:

         // A time-out occurred. This would happen if some value other 
         // than INFINITE is used in the Wait call and no changes occur.
         // In a single-threaded environment, you might not want an
         // INFINITE wait.

            printf("\nNo changes in the time-out period.\n");
            break;

         default: 
            printf("\n ERROR: Unhandled dwWaitStatus.\n");
            ExitProcess(GetLastError());
            break;
      }
   }
}
3 голосов
/ 02 декабря 2008

Возможно, это излишне, но альтернативой может быть IFS kit от MS или FDDK от OSR. Создайте свой собственный драйвер фильтра файловой системы с простым мониторингом всех изменений в файловой системе.

2 голосов
/ 04 октября 2008

ReadDirectoryChangesW

Отличный пример кода в этой статье CodeProject

1 голос
/ 11 сентября 2008

Возможно, вы можете использовать журнал изменений NTFS 5 с DeviceIoControl, как объяснено здесь

1 голос
/ 11 сентября 2008

Если вы не можете запустить процесс при изменении, вы ничего не можете сделать, кроме как сканировать файловую систему и проверить дату / время изменения. Это требует от вас сохранения последней даты / времени каждого файла и сравнения.

Вы можете ускорить это, используя архивный бит (хотя это может испортить ваше ПО для резервного копирования, поэтому продолжайте осторожно).

Бит архива является атрибутом файла присутствует во многих компьютерных файловых системах, особенно FAT, FAT32 и NTFS. Цель бита архива - отслеживать постепенные изменения в файлах для цель резервного копирования, также называется архивирование.

Поскольку бит архива является двоичным, он либо 1, либо 0, либо в этом случае больше часто вызываемый set (1) и clear (0). Операционная система устанавливает бит архива в любое время, когда файл создан, перемещен, переименован или иным образом модифицировано любым способом. Архив бит поэтому представляет собой одно из двух состояния: «изменен» и «не изменен» с момента последнего резервного копирования.

Архивные биты не подвержены влиянию просто читая файл. Когда файл скопировано, исходный файл архива бит не влияет, однако копия бит архива будет установлен во время копия сделана.

Таким образом, процесс будет:

  1. Очистить бит архива для всех файлов
  2. Позволяет файловой системе меняться со временем
  3. Сканирование всех файлов - любые с установленным битом архива были изменены

Это избавит вашу программу от необходимости сохранять состояние, а поскольку вы просматриваете только записи каталога (где хранится бит) и они кластеризованы, это должно быть очень и очень быстро.

Однако, если вы можете запустить процесс во время изменений, вам нужно взглянуть на класс FileSystemWatcher . Вот пример того, как вы можете его использовать.

Он также существует в .NET (для будущих исследователей этого типа проблем)

Возможно, вы можете оставить процесс запущенным на машине, наблюдая за изменениями и создавая файл, который вы сможете прочитать позже.

-Adam

0 голосов
/ 11 сентября 2008

Из двойного поста кто-то упомянул: WMI Event Sink

Тем не менее все еще ищу лучший ответ.

0 голосов
/ 11 сентября 2008

Ничего легкого - если у вас есть работающее приложение, вы можете использовать apis уведомления об изменении файла Win32 (FindFirstChangeNotification), как предложено с другими ответами. предупреждение: около 2000 антивирусных сканеров Trend Micro в реальном времени объединяет изменения, что делает необходимым использование очень больших буферов при запросе списков изменений файловой системы.

Если у вас нет запущенного приложения, вы можете включить ведение журнала ntfs и сканировать журнал на наличие изменений http://msdn.microsoft.com/en-us/library/aa363798(VS.85).aspx, но это может быть медленнее, чем сканирование всего каталога, когда число изменений больше, чем # файлов.

0 голосов
/ 11 сентября 2008

Если вы не против использования .NET, класс FileSystemWatcher справится с этим довольно легко.

...