有关通过 ReadDirectoryChangesW 获取最后文件更改的一些问题

问题描述 投票:0回答:1

我已经实现了一个程序,该程序在重叠模式下使用

ReadDirectoryChangesW
和完成例程来跟踪给定文件夹中的更改。 效果很好。

我计划重建它以制作一个更通用的库 - 完成例程应该将文件更改保存在队列中。

问题:如何将参数传递给完成例程

cr
,该参数将指向我的队列以供在
cr
中使用?

当调用完成例程

cr
并显示文件更改时,我需要继续跟踪:请参阅第
DoRDC = true; // RESTART WATCHING
行。

这是可能的,因为它在循环中运行

while (_kbhit() == 0) {
。 重建后我将消除这个循环。

我的代码如下。主要函数-WatchDirectory();


void DisplayFileInfo(LPVOID FileInfoRecords, DWORD FileInfoLength) {
    // Display file changes. Called from completion routine "cr".

    //ActionText[0] = L"-";

    FILE_NOTIFY_INFORMATION* fi = (FILE_NOTIFY_INFORMATION*)FileInfoRecords;

    if (FileInfoLength == 0) {
        std::wcout << L"No file info!" << std::endl;
        return;
    }

    int RecNum = 1;
    DWORD OffsetToNext = 0;

    do {

        fi = (FILE_NOTIFY_INFORMATION*)(((char*)fi) + OffsetToNext);

        std::wstring wfname;
        std::wstring wActionName;

        if ((fi->Action < MIN_ACTION_CODE) || (fi->Action > MAX_ACTION_CODE))
            wActionName = L"Unknown code";
        else
            wActionName = ActionText[fi->Action];

        int slen = fi->FileNameLength / sizeof(WCHAR);
        wfname.assign(fi->FileName, slen);

        std::wcout << L"Rec " << RecNum << L": Action = " << wActionName << L"(" << fi->Action << L")  Offset = " << fi->NextEntryOffset <<
            L"     File = " << wfname << std::endl;

        OffsetToNext = fi->NextEntryOffset;

        assert(RecNum < 50);

        RecNum++;
    } while (OffsetToNext > 0);

}

LPVOID lpBuffer = NULL;
bool DoRDC = true;


VOID WINAPI cr(DWORD dwErrorCode,                
                DWORD dwNumberOfBytesTransfered,
                LPOVERLAPPED lpOverlapped) {
    // Completion routine

    DoRDC = true; // RESTART WATCHING

    std::wcout << L" ------------- lpCompletionRoutine --------------- " << std::endl;
    std::wcout << L"   ErrCode = " << dwErrorCode
        << L"  BytesTransferred = " << dwNumberOfBytesTransfered << std::endl;

    if (dwErrorCode != 0) {

        return;
    }

    std::wcout << L"..............." << std::endl;

    DisplayFileInfo(lpBuffer, dwNumberOfBytesTransfered);

}


bool WatchDirectory(LPTSTR lpDir)
{
    DWORD dwWaitStatus;
    HANDLE dwChangeHandles[2];
    TCHAR lpDrive[4];
    TCHAR lpFile[_MAX_FNAME];
    TCHAR lpExt[_MAX_EXT];

    HANDLE hDir = INVALID_HANDLE_VALUE;

    std::wcout << L"3_Watching for: " << lpDir << std::endl;

    _tsplitpath_s(lpDir, lpDrive, 4, NULL, 0, lpFile, _MAX_FNAME, lpExt, _MAX_EXT);

    lpDrive[2] = (TCHAR)'\\';
    lpDrive[3] = (TCHAR)'\0';

    int EventsNumber = 1;

    DWORD Flags = FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_FILE_NAME;

    hDir = CreateFile(lpDir, GENERIC_READ, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
        FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, NULL);

    if (hDir == INVALID_HANDLE_VALUE) {

        DWORD err = GetLastError();
        std::wcout << L"ERROR: CreateFile(folder to trace) function failed = " << err << std::endl;
        return false;
        ///ExitProcess(err);
    }


    DWORD nBufferLength = 30000;
    lpBuffer = malloc(nBufferLength);
    BOOL bWatchSubtree = TRUE;
    DWORD BytesReturned = 0;

    HANDLE hEvent = CreateEvent(NULL, FALSE /*manual reset = true*/, FALSE /* initial state*/, NULL);
    if (hEvent == NULL) {
        printf("\n Cannot create event.\n");
        CloseHandle(hDir);
        return false;
        //ExitProcess(GetLastError());
    }

    // =============================================================
    OVERLAPPED Overlapped;
    //---Overlapped.hEvent = hEvent;
    LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine = cr;

    // =============================================================

    DoRDC = true;
    while (_kbhit() == 0) {
        if (DoRDC) {
            ZeroMemory(&Overlapped, sizeof(Overlapped));
            BOOL res_rdc = ReadDirectoryChangesW(hDir,
                lpBuffer,
                nBufferLength,
                bWatchSubtree,
                Flags,
                &BytesReturned,
                &Overlapped,
                lpCompletionRoutine);

            bool ok_rdc = (res_rdc != 0);
            if (ok_rdc) {

            }
            else {
                DWORD err = GetLastError();
                std::wcout << L"ReadDirectoryChangesW error = " << err << std::endl;
            }

            DoRDC = false;
        }

        // Wait for notification.
        //std::wcout << L"SleepEx" << std::endl;

        SleepEx(1000, TRUE);
    }


    CloseHandle(hEvent);

    CloseHandle(hDir);

    free(lpBuffer);
}

c++ winapi readdirectorychangesw
1个回答
0
投票

定义一个自定义

struct
,其中包含
OVERLAPPED
作为其第一个字段,以及您需要的任何其他字段,例如(指向)队列的指针。然后在
struct
LPOVERLAPPED
参数中传递一个指向
ReadDirectoryChangesW()
的指针,并且
cr()
可以将
LPOVERLAPPED
指针投射回您的
struct
以访问其成员。

这是在重叠 I/O 操作中传递自定义数据的常见方法

© www.soinside.com 2019 - 2024. All rights reserved.