C++ 我可以使用c+;中的ReadDirectoryChangesW()查看多个目录的更改吗+;?
我尝试使用C++ 我可以使用c+;中的ReadDirectoryChangesW()查看多个目录的更改吗+;?,c++,windows,winapi,C++,Windows,Winapi,我尝试使用ReadDirectoryChangesW监视不同目录的更改,并成功地使用它监视单个目录。但是,当涉及到监视多个目录时,我遇到的问题是,第一个目录被分配给句柄,它只在该目录中查找更改,然后仅在满足第一个目录条件的情况下才查看下一个目录。但我想同时观看多个目录。我能帮我解决这个问题吗 我附上下面的代码作为参考 #include <iostream> #include <windows.h> #include <stdio.h> #include <
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++;
}
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括“系统/状态h”
#包括
使用名称空间std;
互斥m1;
int main()
{
句柄hDir[20];
矢量目录表;
字符串f_路径;
字符串temp1;
ifpfile;
打开(“C:\\Users\\sathish-pt1608\\Desktop\\path_file.txt”);
如果(!pfile.is_open())
不能说出你的名字;
}
closedir(dir);
}
其他的
{
perror(“请检查目录路径…”);
退出失败;
}
}
}
对于(int i=0;i 您可以,但您需要将其作为一个异步操作来执行,或者只使用LPOVERLAPPED参数,或者同时使用LPOVERLAPPED参数和完成例程。正如文档所说,如果您使用后一种方法,您将需要处于可警报的等待状态。您可以使用名为journals的windows功能来检测删除/更改/创建的文件/fol驱动器上的数据。您需要使用CreateFile()打开驱动器,然后使用DeviceIoControl()不时读取更改的缓冲区。您将获得文件详细信息,如大小、名称、属性等。文件被视为记录,记录大小是使用DeviceIoControl()返回的缓冲区和字节数获得的
创建windows中的日志是为了快速/更方便地查找卷中的更改,因为可能会不时发生多个更改。您可以使用参数FSCTL_QUERY_USN_JOURNAL创建日志和FSCTL_ENUM_USN_数据来查找所需的记录
要了解更多关于期刊的信息,您需要参考msdn链接
伪源代码
///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);
}
///C驱动器
手柄驱动;
drive=CreateFile(L“\\?\\c:”,通用读取,文件共享删除,文件共享读取,文件共享写入,NULL,始终打开,文件标志无缓冲,NULL);
if(无效的\u句柄\u值==驱动器)
{
printf(“创建文件:%u\n”,GetLastError());
返回0;
}
if(!DeviceIoControl(驱动器、FSCTL\u查询、USN\u日志、NULL、0、缓冲区、缓冲区大小和字节数、NULL))
{
printf(“FSCTL_QUERY_USN_JOURNAL:%u\n”,GetLastError());
返回0;
}
USN_JOURNAL_DATA*JOURNAL=(USN_JOURNAL_DATA*)缓冲区;
MFT_ENUM_DATA MFT_ENUM_DATA={0};
mft_enum_data.StartFileReferenceNumber=0;
mft_enum_data.LowUsn=0;
mft_enum_data.HighUsn=journal->MaxUsn;
对于(;;)
{
if(!DeviceIoControl(驱动器、FSCTL_ENUM_USN_数据和mft_ENUM_数据、sizeof(mft_ENUM_数据)、缓冲区、缓冲区大小和字节数,NULL))
{
printf(“FSCTL_ENUM_USN_数据:%u\n”,GetLastError());
返回0;
}
USN_记录*记录;
USN_记录*recordend;
记录=(USN_记录*)((USN*)缓冲区+1);
recordend=(USN_记录*)((字节*)缓冲区)+字节计数;
DWORDLONG filecount=0;
while(记录<记录结束)
{
filecount++;
printf(“文件属性:%x\n”,记录->文件属性);
printf(“文件名长度:%u\n”,(DWORD)记录->文件名长度);
printf(“记录长度:%u\n”,记录->记录长度);
WCHAR*文件名;
WCHAR*文件名结束;
文件名=(WCHAR*)((字节*)记录)+记录->文件名偏移量);
filenameend=(WCHAR*)((字节*)记录)+记录->文件名偏移量+记录->文件名长度);
printf(“文件名:%s\n”,文件名);
记录=(USN_记录*)((字节*)记录)+记录->记录长度;
}
mft_enum_data.StartFileReferenceNumber=*((DWORDLONG*)缓冲区);
}
但我想同时查看多个目录。--学习多线程编程远远超出了简单答案的范围。即使我使用多线程编程,我也不想为每个目录创建线程。这肯定会降低系统的性能。因此,我创建了一个恒定的线程数,并检查t他通过在线程之间均匀分布多个目录。@paul为什么需要多个线程?提供了一个很好的概述,还提供了使用完成端口跟踪大量目录更改的示例代码。我已经浏览了指定的链接。我无法清楚地理解当一个参与者您提到的createFile()
中提到了ular目录。它给出了意外的结果。示例代码提供了驱动器C中文件的详细信息。您可以尝试pc中的任何驱动器。它在createFile()中失败
语句本身,不返回任何属性..我工作的平台有问题吗。?你能检查GetLastError()并告诉我问题吗?我想它可能需要更高级别的权限来执行CreateFile()GetLastError()返回5