Проблема с файлом ReadDirectoryChangesW при сохранении в Visual Studio 2019 - PullRequest
0 голосов
/ 05 февраля 2020

Я использую ReadDirectoryChangesW, чтобы определить, когда файл .hlsl в каталоге изменяется. Он отлично работает при сохранении файла с помощью Notepad / Notepad ++ / VSCode, но когда я пытаюсь сохранить файл в Visual Studio 2019, получаю странный вывод. Имя папки сохраняется, но имя и расширение файла: gibberi sh.

Так выглядит мой код. Он запускается в отдельном потоке, который вызывается при запуске приложения.

void ShaderReloadWatcher::BeginWatching()
{
    m_thread = std::thread(&ShaderReloadWatcher::WatchShaderDirectory, this);
}

Основной поток l oop:

void ShaderReloadWatcher::WatchShaderDirectory()
{
    LPCTSTR shaderDir = "../Source/Shaders";
    HANDLE shaderFolderHandle = CreateFile(
        shaderDir,
        GENERIC_READ,
        FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
        OPEN_EXISTING,
        FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,
        NULL);

    char notifyBuffer[1024];

    OVERLAPPED ovl = { 0 };
    ovl.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    DWORD error = ReadDirectoryChangesW(
        shaderFolderHandle,
        &notifyBuffer,
        sizeof(notifyBuffer),
        TRUE,
        FILE_NOTIFY_CHANGE_LAST_WRITE,
        NULL, &ovl, NULL);


    while (true)
    {
        DWORD result = WaitForSingleObject(ovl.hEvent, 0);

        switch (result)
        {
        case WAIT_TIMEOUT:
        {
            break;
        }

        case WAIT_OBJECT_0:
        {
            DWORD bytesTransferred;
            GetOverlappedResult(shaderFolderHandle, &ovl, &bytesTransferred, FALSE);

            OnDirectoryFileChange(notifyBuffer);

            ResetEvent(ovl.hEvent);

            DWORD error = ReadDirectoryChangesW(
                shaderFolderHandle,
                &notifyBuffer,
                sizeof(notifyBuffer),
                TRUE,
                FILE_NOTIFY_CHANGE_LAST_WRITE,
                NULL, &ovl, NULL);

            break;
        }

        }
    }

    CloseHandle(shaderFolderHandle);
}

OnDirectoryFileChange:

void ShaderReloadWatcher::OnDirectoryFileChange(char* buffer)
{
    DWORD offset = 0;
    FILE_NOTIFY_INFORMATION* fileNotifyInfo = nullptr;
    char fileName[1024];

    do 
    {
        memset(fileName, NULL, sizeof(fileName));
        fileNotifyInfo = reinterpret_cast<FILE_NOTIFY_INFORMATION*>(&buffer[offset]);

        WideCharToMultiByte(CP_ACP, NULL, fileNotifyInfo->FileName, fileNotifyInfo->FileNameLength / sizeof(WCHAR), fileName, sizeof(fileName), NULL, NULL);

        printf("%s\n", fileName);

        offset += fileNotifyInfo->NextEntryOffset;
    } while (fileNotifyInfo->NextEntryOffset != 0);
}

This это вывод, который я получаю при сохранении (один раз) с помощью Блокнота ++:

D3D11\light_pixel.hlsl
D3D11\light_pixel.hlsl

Я узнал, что он печатается несколько раз из-за того, как текстовые редакторы записывают в файл, так что это ожидаемо.

Тем не менее, при сохранении с Visual Studio, я получаю это.

D3D11\sfpwwek3.vs4~
D3D11
D3D11
D3D11
D3D11

Имя папки (D3D11) выглядит хорошо, но все имя файла gibberi sh. Это также разные гиббери sh каждый раз:

D3D11\5uuwurye.nel~
D3D11
D3D11
D3D11
D3D11

Кодировка установлена ​​на западноевропейскую (CP 1252), и я пробовал использовать разные, такие как Unicode (CP 65001), но я все еще получаю тот же результат.

Я наблюдал за значением fileNotifyInfo->FileName, и с самого начала оно выглядит как gibberi sh, так что нет ничего плохого в преобразовании WideCharToMultiByte, которое вызывает эту проблему.

Любая помощь в понимании этой проблемы очень ценится, спасибо!

1 Ответ

1 голос
/ 05 февраля 2020

Проблема решена - благодаря @Ted Lyngmo.

Я только слушал изменения записи, и кажется, что Visual Studio сначала записывала имя временного файла, а затем переименовывала его в правильное имя. Я добавил FILE_NOTIFY_CHANGE_FILE_NAME и теперь вывод выглядит так:

D3D11\cn42zizu.cht~
D3D11\cn42zizu.cht~
D3D11
D3D11\light_pixel.hlsl~RF62be0e8e.TMP
D3D11\light_pixel.hlsl~RF62be0e8e.TMP
D3D11\light_pixel.hlsl
D3D11\light_pixel.hlsl~RF62be0e8e.TMP
D3D11
D3D11\cn42zizu.cht~
D3D11\light_pixel.hlsl
D3D11
D3D11\light_pixel.hlsl~RF62be0e8e.TMP
D3D11

Множество сообщений, но правильное имя там!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...