提问人:tearfur 提问时间:11/15/2023 最后编辑:Remy Lebeautearfur 更新时间:11/16/2023 访问量:96
使用“MoveFileA”重命名文件夹,其中文件打开的文件句柄
Rename folder using `MoveFileA` with open file handles of the files inside
问:
我有一种情况,我需要用它来重命名一个文件夹,该文件夹包含一些具有打开文件句柄的文件(在同一过程中)。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;
}
答:
0赞
tearfur
11/16/2023
#1
事实证明,在这两种情况下都不应该重命名文件夹,我的测试程序证明了这一点。MoveFileA()
我不知道我或我的电脑发生了什么,因为我可以发誓正在工作。很抱歉浪费了大家的时间。create3Handles()
评论