You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用GetFileInformationByHandleEx读取junction point目录中的文件

问题原因与解决方案

核心问题根源

  • 你添加FILE_FLAG_OPEN_REPARSE_POINT标志的操作不符合需求:该标志的作用是让CreateFile直接打开重解析点(junction point)本身,而不会跟随重解析指向它映射的目标目录。此时你拿到的句柄对应的是存储重解析配置数据的特殊对象,不是实际的文件目录,自然只能读取到.和..两个默认条目,无法获取目标目录下的真实文件列表。
  • 最初未加该标志时返回ERROR_INVALID_PARAMETER(错误码0x57),是因为FileIdInfo、FileIdExtdDirectoryInfo这两类信息查询,对跨卷重解析得到的目录句柄兼容性较差,部分Windows版本下直接对重解析后的目录句柄调用会参数校验失败。

修复方案

步骤1:还原CreateFile调用

去掉FILE_FLAG_OPEN_REPARSE_POINT标志,保证CreateFile自动跟随重解析打开实际的目标目录:

auto h = CreateFile(path, FILE_LIST_DIRECTORY, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);

步骤2:调整查询逻辑

两种可选方案,根据你的需求选择:

  1. 如果仅需要遍历目录内容,优先使用兼容性更好的FileDirectoryInfo代替FileIdExtdDirectoryInfo,不需要额外修改其他逻辑即可正常遍历junction映射的目录内容。
  2. 如果必须获取文件ID信息,先通过GetFinalPathNameByHandleW获取重解析指向的实际目录路径,再重新打开该实际路径得到新句柄,用新句柄调用GetFileInformationByHandleEx查询FileId相关信息即可避免参数错误。

修复后参考代码

#include <windows.h>
#include <stdio.h>

int main()
{
    wchar_t path[1024] = L"C:\\MyPath\\MyDir";
    
    auto h = CreateFile(path, FILE_LIST_DIRECTORY, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
    if (h == INVALID_HANDLE_VALUE)
    {
        printf("CreateFile error: 0x%08X\n", GetLastError());
        return 0;
    }

    // 先拿实际目标路径,如果需要查询FileId就用这个路径重新打开
    wchar_t targetPath[1024] = {0};
    GetFinalPathNameByHandleW(h, targetPath, ARRAYSIZE(targetPath), FILE_NAME_NORMALIZED);
    wprintf(L"实际指向路径:%s\n", targetPath);

    unsigned char buffer[4096];
    do
    {
        // 改用FileDirectoryInfo保证兼容性
        if (!GetFileInformationByHandleEx(h, FILE_INFO_BY_HANDLE_CLASS::FileDirectoryInfo, buffer, ARRAYSIZE(buffer)))
        {
            auto gle = GetLastError();
            if (gle == ERROR_NO_MORE_FILES)
                break;

            printf("FileDirectoryInfo error: 0x%08X\n", gle);
            break;
        }

        auto current = buffer;
        do
        {
            auto info = (FILE_DIRECTORY_INFO*)current;
            wprintf(L"name: %.*s\n", info->FileNameLength / 2, info->FileName);
            if (!info->NextEntryOffset)
                break;

            current += info->NextEntryOffset;
        } while (true);
    } while (true);
    CloseHandle(h);
}

内容的提问来源于stack exchange,提问作者Alfonso-Rachid Huilda

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 18:03:03