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

如何通过WinAPI获取盘符及物理驱动器的文件系统信息?

在Windows环境下,要搞清楚逻辑盘符(比如C:/、D:/)或者物理驱动器(比如//./PhysicalDrive0)的文件系统类型(比如是不是NTFS),最靠谱的方式就是直接调用Windows API来实现。下面分两种场景给你具体的实现思路和代码示例(用C++写的,毕竟直接调用系统接口最直观):

一、获取逻辑盘符的文件系统信息

对于C:/这类逻辑盘符,用GetVolumeInformation这个API就足够了,它能直接返回盘符的文件系统名称,不用绕弯子。

代码示例:

#include <windows.h>
#include <iostream>
#include <string>

bool IsDriveNTFS(const std::wstring& drivePath) {
    WCHAR fileSystemName[MAX_PATH] = {0};
    // 调用GetVolumeInformation,获取文件系统名称
    if (!GetVolumeInformationW(
        drivePath.c_str(),
        nullptr, 0,  // 不需要卷标信息
        nullptr,    // 不需要序列号
        nullptr,    // 不需要最大组件长度
        nullptr,    // 不需要文件系统标志
        fileSystemName,
        MAX_PATH
    )) {
        std::cerr << "Failed to get volume information. Error code: " << GetLastError() << std::endl;
        return false;
    }

    // 不区分大小写比较文件系统名称
    return _wcsicmp(fileSystemName, L"NTFS") == 0;
}

int main() {
    std::wstring drive = L"C:\\";
    if (IsDriveNTFS(drive)) {
        std::wcout << drive << " is NTFS." << std::endl;
    } else {
        std::wcout << drive << " is not NTFS." << std::endl;
    }
    return 0;
}

关键点说明:

  • 传入的盘符路径必须以\\结尾(比如L"C:\\"),不然API会调用失败。
  • _wcsicmp是不区分大小写的字符串比较,避免因为大小写问题误判。
  • 调用失败时用GetLastError()能拿到具体错误码,方便排查(比如盘符不存在、权限不足等)。
二、获取物理驱动器的文件系统信息

物理驱动器本身没有单一的文件系统——它是由多个分区组成的,每个分区有自己的文件系统。所以我们得先枚举物理驱动器上的所有分区,再逐个查询每个分区的文件系统类型。

这里需要用到几个IOCTL控制码:IOCTL_DISK_GET_DRIVE_GEOMETRY_EX(获取驱动器几何信息和分区表),然后针对每个分区打开对应的设备(比如//./PhysicalDrive0Partition1),再用GetVolumeInformation或者IOCTL_VOLUME_GET_VOLUME_INFORMATION查询文件系统。

代码示例:

#include <windows.h>
#include <iostream>
#include <string>
#include <vector>

// 简化的分区信息结构体
struct PartitionInfo {
    LARGE_INTEGER offset;
    LARGE_INTEGER length;
    int number;
};

// 枚举物理驱动器上的所有分区
std::vector<PartitionInfo> EnumeratePartitions(const std::wstring& physicalDrivePath) {
    std::vector<PartitionInfo> partitions;

    HANDLE hDrive = CreateFileW(
        physicalDrivePath.c_str(),
        GENERIC_READ,
        FILE_SHARE_READ | FILE_SHARE_WRITE,
        nullptr,
        OPEN_EXISTING,
        0,
        nullptr
    );

    if (hDrive == INVALID_HANDLE_VALUE) {
        std::cerr << "Failed to open physical drive. Error code: " << GetLastError() << std::endl;
        return partitions;
    }

    // 获取驱动器几何信息和分区表
    DISK_GEOMETRY_EX geometryEx = {0};
    DWORD bytesReturned = 0;
    if (!DeviceIoControl(
        hDrive,
        IOCTL_DISK_GET_DRIVE_GEOMETRY_EX,
        nullptr, 0,
        &geometryEx, sizeof(geometryEx),
        &bytesReturned,
        nullptr
    )) {
        std::cerr << "Failed to get drive geometry. Error code: " << GetLastError() << std::endl;
        CloseHandle(hDrive);
        return partitions;
    }

    // 遍历分区表(兼容MBR/GPT,API会自动返回对应类型)
    PARTITION_INFORMATION_EX* pPartitions = reinterpret_cast<PARTITION_INFORMATION_EX*>(geometryEx.Buffer);
    DWORD partitionCount = geometryEx.PartitionCount;

    for (DWORD i = 0; i < partitionCount; ++i) {
        PartitionInfo info;
        info.offset = pPartitions[i].StartingOffset;
        info.length = pPartitions[i].PartitionLength;
        info.number = i + 1;  // 分区编号从1开始
        partitions.push_back(info);
    }

    CloseHandle(hDrive);
    return partitions;
}

// 查询指定分区是否为NTFS
bool IsPartitionNTFS(const std::wstring& physicalDrivePath, int partitionNumber) {
    // 构造分区设备路径,比如//./PhysicalDrive0Partition1
    std::wstring partitionPath = physicalDrivePath + L"Partition" + std::to_wstring(partitionNumber);

    HANDLE hPartition = CreateFileW(
        partitionPath.c_str(),
        GENERIC_READ,
        FILE_SHARE_READ | FILE_SHARE_WRITE,
        nullptr,
        OPEN_EXISTING,
        0,
        nullptr
    );

    if (hPartition == INVALID_HANDLE_VALUE) {
        std::cerr << "Failed to open partition " << partitionNumber << ". Error code: " << GetLastError() << std::endl;
        return false;
    }

    WCHAR fileSystemName[MAX_PATH] = {0};
    bool isNTFS = false;

    // 先尝试用GetVolumeInformation查询
    if (GetVolumeInformationW(
        partitionPath.c_str(),
        nullptr, 0,
        nullptr,
        nullptr,
        nullptr,
        fileSystemName,
        MAX_PATH
    )) {
        isNTFS = (_wcsicmp(fileSystemName, L"NTFS") == 0);
    } else {
        // 如果失败, fallback 到IOCTL直接查询分区设备
        VOLUME_INFORMATION_BUFFER volumeInfo = {0};
        DWORD bytesReturned = 0;
        if (DeviceIoControl(
            hPartition,
            IOCTL_VOLUME_GET_VOLUME_INFORMATION,
            nullptr, 0,
            &volumeInfo, sizeof(volumeInfo),
            &bytesReturned,
            nullptr
        )) {
            isNTFS = (_wcsicmp(volumeInfo.FileSystemName, L"NTFS") == 0);
        } else {
            std::cerr << "Failed to get partition volume info. Error code: " << GetLastError() << std::endl;
        }
    }

    CloseHandle(hPartition);
    return isNTFS;
}

int main() {
    std::wstring physicalDrive = L"\\\\.\\PhysicalDrive0";
    auto partitions = EnumeratePartitions(physicalDrive);

    if (partitions.empty()) {
        std::wcout << "No partitions found on " << physicalDrive << std::endl;
        return 1;
    }

    for (const auto& part : partitions) {
        bool isNTFS = IsPartitionNTFS(physicalDrive, part.number);
        std::wcout << physicalDrive << L"Partition" << part.number << " is " << (isNTFS ? L"NTFS" : L"not NTFS") << std::endl;
    }

    return 0;
}

关键点说明:

  • 打开物理驱动器需要管理员权限,不然会提示权限不足(错误码5)。
  • 有些分区没有挂载盘符,GetVolumeInformation会失败,这时候用IOCTL_VOLUME_GET_VOLUME_INFORMATION直接从分区设备获取信息更可靠。
  • 分区设备的命名规则是//./PhysicalDriveXPartitionY,X是驱动器编号,Y是分区编号(从1开始)。

如果用C#、Python这类语言,思路也一样——通过P/Invoke(C#)或者ctypes(Python)调用对应的Windows API即可,核心逻辑没有区别。

内容的提问来源于stack exchange,提问作者Tomasz Nowakowski

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 12:28:13