Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 我可以使用c+;中的ReadDirectoryChangesW()查看多个目录的更改吗+;?_C++_Windows_Winapi - Fatal编程技术网

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