c++ 使用“MoveFileA”打开文件夹,其中包含文件的打开文件句柄

fruv7luv  于 11个月前  发布在  其他
关注(0)|答案(1)|浏览(94)

我有一个情况,我需要使用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;
}

字符串

nmpmafwu

nmpmafwu1#

事实证明,MoveFileA()在这两种情况下都不能重命名文件夹,我的测试程序证明了这一点。
我不知道是什么让我或我的电脑,因为我可以发誓create3Handles()是工作。对不起,浪费大家的时间。

相关问题