我正在尝试使用ReadDirectoryChangesW
监视不同的目录以进行更改,并且我成功使用它监视单个目录。但是当涉及到监视多个目录时,我遇到的问题是第一个目录被分配给句柄,它只在该目录中查找更改,然后只有在满足第一个目录条件时才会查看下一个目录。但我想同时观看多个目录。我可以帮我解决这个问题吗?
我附上以下代码供参考。
#include <iostream>
#include <windows.h>
#include <stdio.h>
#include <vector>
#include <fstream>
#include <mutex>
#include "sys/stat.h"
#include <dirent.h>
using namespace std;
mutex m1;
int main()
{
HANDLE hDir[20];
vector <string> directory_list;
string f_path;
string temp1;
ifstream pfile;
pfile.open("C:\\Users\\sathish-pt1608\\Desktop\\path_file.txt");
if (!pfile.is_open())
cout << "Unable to open the Requested File...";
while(pfile.good())
{
getline(pfile,f_path);
struct stat path_stat;
stat(f_path.c_str(),&path_stat);
if (S_ISREG(path_stat.st_mode))
{
int a = f_path.find_last_of('\\');
directory_list.push_back(f_path.substr(0, a - 1));
}
else if(S_ISDIR(path_stat.st_mode))
{
DIR *dir;
struct dirent *ent;
dir = opendir(f_path.c_str());
if (dir != NULL)
{
directory_list.push_back(f_path);
while ( (ent = readdir(dir)) != NULL)
{
temp1 = ent->d_name;
}
closedir(dir);
}
else
{
perror("Please Check the Directory Path...");
EXIT_FAILURE;
}
}
}
for (int i = 0; i < directory_list.size();)
{
LPCTSTR DirName = directory_list[i].c_str();
hDir[i] = CreateFile(DirName, FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
FILE_NOTIFY_INFORMATION Buffer[1024];
DWORD BytesReturned;
if (!ReadDirectoryChangesW(hDir[i], &Buffer, sizeof(Buffer), TRUE, FILE_NOTIFY_CHANGE_LAST_WRITE, &BytesReturned, NULL, NULL))
{
cout << DirName << endl;
}
else
cout << "THE DIRECTORY HAS BEEN MODIFIED..." << endl;
if (i == directory_list.size() - 1)
i = 0;
else
i++;
}
}
答案 0 :(得分:1)
您可以使用名为日志的Windows功能来检测驱动器上已删除/已更改/创建的文件/文件夹。您需要使用CreateFile()打开驱动器,然后使用DeviceIoControl()不时读取更改的缓冲区。您将获得文件详细信息,如大小,名称,属性等。文件被视为记录,记录大小是使用DeviceIoControl()和bytecount返回的缓冲区获得的。
创建Windows中的日记帐以便以快速/简单的方式查找卷中的更改,因为可能会不时发生多个更改。您可以使用参数FSCTL_QUERY_USN_JOURNAL创建日记和FSCTL_ENUM_USN_DATA以查找所需的记录。
要了解有关期刊的更多信息,请参阅msdn link https://msdn.microsoft.com/en-us/library/windows/desktop/aa363798(v=vs.85).aspx
虚拟源代码,
///C drive
HANDLE drive;
drive = CreateFile(L"\\\\?\\c:", GENERIC_READ, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_FLAG_NO_BUFFERING, NULL);
if (INVALID_HANDLE_VALUE == drive)
{
printf("CreateFile: %u\n", GetLastError());
return 0;
}
if (!DeviceIoControl(drive, FSCTL_QUERY_USN_JOURNAL, NULL, 0, buffer, BUFFER_SIZE, &bytecount, NULL))
{
printf("FSCTL_QUERY_USN_JOURNAL: %u\n", GetLastError());
return 0;
}
USN_JOURNAL_DATA* journal = (USN_JOURNAL_DATA *)buffer;
MFT_ENUM_DATA mft_enum_data = {0};
mft_enum_data.StartFileReferenceNumber = 0;
mft_enum_data.LowUsn = 0;
mft_enum_data.HighUsn = journal->MaxUsn;
for(;;)
{
if (!DeviceIoControl(drive, FSCTL_ENUM_USN_DATA, &mft_enum_data, sizeof(mft_enum_data), buffer, BUFFER_SIZE, &bytecount, NULL))
{
printf("FSCTL_ENUM_USN_DATA: %u\n", GetLastError());
return 0;
}
USN_RECORD* record;
USN_RECORD* recordend;
record = (USN_RECORD *)((USN *)buffer + 1);
recordend = (USN_RECORD *)(((BYTE *)buffer) + bytecount);
DWORDLONG filecount = 0;
while (record < recordend)
{
filecount++;
printf("FileAttributes: %x\n", record->FileAttributes);
printf("FileNameLength: %u\n", (DWORD)record->FileNameLength);
printf("RecordLength: %u\n", record->RecordLength);
WCHAR * filename;
WCHAR * filenameend;
filename = (WCHAR *)(((BYTE *)record) + record->FileNameOffset);
filenameend= (WCHAR *)(((BYTE *)record) + record->FileNameOffset + record->FileNameLength);
printf("FileName: %s\n", filename);
record = (USN_RECORD *)(((BYTE *)record) + record->RecordLength);
}
mft_enum_data.StartFileReferenceNumber = *((DWORDLONG *)buffer);
}
答案 1 :(得分:0)
您可以但您需要将其作为异步操作执行,既可以使用LPOVERLAPPED参数,也可以使用它和完成例程。正如文档所说,如果你走后一条路线,你需要处于警惕的等待状态。