【发布时间】:2020-05-20 18:42:26
【问题描述】:
我正在使用 ReadDirectoryChangesW 来检测目录中的 .hlsl 文件何时更改。使用 Notepad/Notepad++/VSCode 保存文件时效果很好,但是当我尝试在 Visual Studio 2019 中保存文件时,我得到一个奇怪的输出。文件夹名称被保留,但文件名和扩展名是乱码。
这就是我的代码的样子。它在应用程序启动时调用的单独线程上运行。
void ShaderReloadWatcher::BeginWatching()
{
m_thread = std::thread(&ShaderReloadWatcher::WatchShaderDirectory, this);
}
线程主循环:
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,
¬ifyBuffer,
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,
¬ifyBuffer,
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);
}
这是我使用 Notepad++ 保存(一次)时得到的输出:
D3D11\light_pixel.hlsl
D3D11\light_pixel.hlsl
我了解到,由于文本编辑器写入文件的方式,它被多次打印,所以这是意料之中的。
但是,当使用 Visual Studio 保存时,我得到了这个。
D3D11\sfpwwek3.vs4~
D3D11
D3D11
D3D11
D3D11
文件夹名称(D3D11)看起来不错,但文件名全是乱码。每次都是不同的乱码:
D3D11\5uuwurye.nel~
D3D11
D3D11
D3D11
D3D11
编码设置为西欧 (CP 1252),我尝试使用不同的编码,如 Unicode (CP 65001),但仍然得到相同的结果。
我查看了 fileNotifyInfo->FileName 值,它似乎从一开始就是胡言乱语,因此导致此问题的 WideCharToMultiByte 转换似乎没有任何问题。
非常感谢您对理解此问题的任何帮助,谢谢!
【问题讨论】:
-
会不会是临时文件名?它们通常由随机字符生成。如果在关闭 VS 的同时让程序运行,它会变成可识别的东西吗?或许您也应该打开嗅探所有目录更改,以便更清楚地了解发生了什么。
-
循环是错误的,为什么你完全以异步模式打开文件夹而不是同步,文件名 - 不是 0 终止 - 所以使用 %s 是错误的。你不检查错误
-
@TedLyngmo 我刚刚通过添加
FILE_NOTIFY_CHANGE_FILE_NAME标志进行了尝试,看来您是正确的!它现在输出更多的东西,包括正确的文件名。谢谢! -
@soomi 太好了。 :-)
-
@RbMm 我再看看循环,谢谢。文件名是 0 终止,因为我在复制值之前将 memset 设置为 NULL。
标签: c++ windows visual-studio visual-studio-2019