Я использую этот код для заполнения базы данных всех файлов на диске:
TCHAR szVolumePath[_MAX_PATH] = L"\\\\.\\d:";
HANDLE hDrive = CreateFile(szVolumePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL);
MFT_ENUM_DATA_V0 med = { 0 };
med.StartFileReferenceNumber = 0;
med.LowUsn = 0;
med.HighUsn = MAXLONGLONG;
DWORD cb;
PUSN_RECORD pRecord;
unsigned char pData[sizeof(DWORDLONG) + 0x10000] = { 0 };
while (DeviceIoControl(hDrive, FSCTL_ENUM_USN_DATA, &med, sizeof(med), pData, sizeof(pData), &cb, NULL) != FALSE)
{
pRecord = (PUSN_RECORD)&pData[sizeof(USN)];
while ((PBYTE)pRecord < (pData + cb))
{
wstring sz((LPCWSTR)(PBYTE)pRecord + pRecord->FileNameOffset, pRecord->FileNameLength / sizeof(WCHAR));
// file the database
pRecord = (PUSN_RECORD)((PBYTE)pRecord + pRecord->RecordLength);
}
med.StartFileReferenceNumber = *(DWORDLONG *)pData;
}
Как только цикл завершен, база данных успешно заполнена.
Но как продолжить (в качестве фоновой задачи) отслеживать в реальном времени изменения / удаления файлов? (пример: отобразить MessageBox()
«Файл readme.txt был переименован.»)
Должен ли я перезапускать такой цикл каждую 1 секунду, с med.StartFileReferenceNumber
= самый высокий FileReferenceNumber, который вы видели раньше?
Примечание: я немного не хочу запускать этот код каждую 1 секунду (99% времени, даром). Делая это каждые 10 секунд, вы избежите использования такого большого количества ресурсов, но перед обнаружением изменений будет задержка, в то время как я знаю некоторые программы индексирования, которые не имеют такой задержки.
Примечание 2: я читаю Как я могу обнаружить только удаленные, измененные и созданные файлы на томе? но цель основного ответа — запустить его один раз, а не постоянно в фоновом режиме.
Примечание 3: я посмотрел на этот полезный пример кода от Microsoft Следить за дисками NTFS: объяснение журнала изменений Windows 2000 .
Примечание 4: я должен держать FSCTL_ENUM_USN_DATA для начальной загрузки базы данных, а затем использовать FSCTL_READ_USN_JOURNAL вместо?
Note5: ReadDirectoryChangesW
или же FindNextChangeNotification
(первый дает полный путь изменений в уведомлениях, второй нет) не может быть использован, потому что он не даст FileReferenceNumber
удаленного файла (нужно открыть файл и использовать NtQueryInformationFile
получить это; но это невозможно для удаленных файлов); и FileReferenceNumber необходим для обновления файловая база данных (файловая база данных использует карту / словарь с FileReferenceNumbers в качестве ключей).
Задача ещё не решена.
Других решений пока нет …