1

我正在使用此代码来填充磁盘上所有文件的数据库:

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 Keeping an Eye on Your NTFS Drives 中的这个有用的代码示例:Windows 2000 Change Journal Explained

注意4:我是否应该保留FSCTL_ENUM_USN_DATA用于初始数据库加载,然后使用FSCTL_READ_USN_JOURNAL代替?

注意5:ReadDirectoryChangesW或者FindNextChangeNotification(前者给出了通知中更改的完整路径,后者没有)不能真正使用,因为它不会给出FileReferenceNumber已删除文件的 (必须打开文件并使用NtQueryInformationFile才能获取它;但这对于已删除的文件是不可能的);并且 FileReferenceNumber 是更新文件数据库所必需的(文件数据库使用以 FileReferenceNumbers 作为键的映射/字典)。

4

0 回答 0