Как узнать, изменился ли вложенный файл каталога

StackOverflow https://stackoverflow.com/questions/56682

  •  09-06-2019
  •  | 
  •  

Вопрос

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

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

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

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

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

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

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

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

Это было полезно?

Решение

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

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;
      }
   }
}

Другие советы

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

ReadDirectoryChangesW Читать

Несколько отличных примеров кода в эта статья CodeProject

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

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

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

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

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

Таким образом, процесс был бы:

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

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

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

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

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

-Адам

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

Если вы не возражаете против использования .ЧИСТЫЙ Просмотр файловой системы класс справится с этим за вас довольно легко.

Из двойного поста, о котором кто-то упоминал:Приемник событий WMI

Тем не менее, я все еще ищу ответ получше.

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top