我有一个情况,我需要使用MoveFileA()
重命名一个文件夹,其中包含一些打开文件句柄的文件(在同一进程中)。
如果所有操作都在同一个线程中完成,则重命名操作有效,但是,如果这些文件句柄是在另一个线程中打开的,则重命名操作将不起作用。
据我所知,Windows文件句柄应该是跨线程共享的。那么,为什么这不起作用呢?
我有一个小的测试程序来演示我的问题。如果我按原样编译并运行它,它会完成而不会出错。但是,如果我注解掉这行:auto handles = create3Handles();
的
并取消这一行的注解:auto handles = create3HandlesInThread();
个
然后MoveFileA()
失败,程序输出:
移动文件夹失败(5)
#include <array>
#include <cstddef>
#include <filesystem>
#include <iostream>
#include <string>
#include <thread>
#include <windows.h>
using namespace std::literals;
static auto constexpr ParentDir = "test-dir";
static auto constexpr ParentDirAfter = "renamed-dir";
std::array<HANDLE, 3U> create3Handles() {
auto handles = std::array<HANDLE, 3U>{};
for (size_t i = 0U; i < std::size(handles); ++i) {
auto filepath = std::string{ParentDir} + '/' + std::to_string(i) + ".txt";
if (handles[i] = CreateFileA(filepath.c_str(),
GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
nullptr,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
nullptr); handles[i] == INVALID_HANDLE_VALUE) {
std::cerr << "Create \"" << filepath << "\" failed (" << GetLastError() << ')' << std::endl;
}
if (BOOL ret = WriteFile(handles[i],
filepath.c_str(),
std::size(filepath) * sizeof(filepath[0]),
nullptr,
nullptr); ret == 0) {
std::cerr << "Write \"" << filepath << "\" failed (" << GetLastError() << ')' << std::endl;
}
}
return handles;
}
[[maybe_unused]] std::array<HANDLE, 3U> create3HandlesInThread() {
auto handles = std::array<HANDLE, 3>{};
auto t = std::thread{[&handles]() { handles = create3Handles(); }};
t.join();
return handles;
}
int main() {
std::filesystem::remove_all({ ParentDir });
std::filesystem::remove_all({ ParentDirAfter });
if (BOOL ret = CreateDirectoryA(ParentDir, nullptr); !ret) {
std::cerr << "Create parent folder failed" << GetLastError() << ')' << std::endl;
return 1;
}
auto handles = create3Handles();
// auto handles = create3HandlesInThread();
if (BOOL ret = MoveFileA(ParentDir, ParentDirAfter); !ret) {
std::cerr << "Move folder failed (" << GetLastError() << ')' << std::endl;
}
for (auto const &handle: handles) {
if (BOOL ret = CloseHandle(handle); !ret) {
std::cerr << "Close file handle failed (" << GetLastError() << ')' << std::endl;
}
}
return 0;
}
字符串
1条答案
按热度按时间nmpmafwu1#
事实证明,
MoveFileA()
在这两种情况下都不能重命名文件夹,我的测试程序证明了这一点。我不知道是什么让我或我的电脑,因为我可以发誓
create3Handles()
是工作。对不起,浪费大家的时间。