GetVolumeInformationA 获取卷标必须传根目录路径(如"C:\"),传驱动器字母(如"C:")会返回空卷标且错误码为0;建议用GetLogicalDrives()枚举驱动器再构造正确路径。

GetVolumeInformationA 能拿到卷标,但必须传对根路径
直接调用 GetVolumeInformationA 获取卷标时,很多人传错参数——它不接受驱动器字母本身(如 "C:"),而必须是带反斜杠的根目录路径(如 "C:\")。传 "C:" 会返回成功但 lpVolumeNameBuffer 为空,且 GetLastError() 返回 0,极具迷惑性。
实操建议:
- 枚举所有驱动器用
GetLogicalDrives()得到位掩码,再用for (int i = 0; i 检查每位,拼出 <code>char rootPath[] = "A:\"这种格式 - 调用前确保
lpVolumeNameBuffer缓冲区至少 256 字节,否则可能截断或触发缓冲区溢出警告 - 注意该函数在无介质的光驱或未格式化的 U 盘上会失败,
GetLastError()返回ERROR_NOT_READY,需跳过处理
EnumWindowsVolumes 需要 Windows 10 1809+,且权限无额外要求
如果目标系统较新(Windows 10 1809 或 Windows Server 2019 起),可用 FindFirstVolumeW / FindNextVolumeW 组合遍历所有卷 GUID 路径(如 "\\?\Volume{a1b2c3d4-...}\"),再对每个卷调用 GetVolumeInformationByHandleW。这套 API 不依赖盘符,能拿到 NTFS 卷标、ReFS 卷标,甚至未分配盘符的卷信息。
关键点:
立即学习“C++免费学习笔记(深入)”;
让 Windows 桌面程序在开机时静默自启并隐藏到系统托盘。特别适用于 Flutter、Electron 等无视 VBS/ProcessStartInfo 窗口样式、难以隐藏的顽固应用。提供「VBS 启动器 + Python ctypes/Win32 API」的隐藏窗口方案,可稳定把窗口收进托盘且不闪控制台。
- 必须用宽字符版本(
W后缀),FindFirstVolumeA在 Windows 中根本不存在 - 每个卷 GUID 路径需先用
CreateFileW以GENERIC_READ和FILE_FLAG_BACKUP_SEMANTICS打开,才能传给GetVolumeInformationByHandleW - 打开失败常见原因是权限不足——但其实普通用户进程也能成功,只要不访问卷内文件;失败时
GetLastError()多为ERROR_ACCESS_DENIED,可安全忽略并继续下一个卷
卷标为空或乱码?检查文件系统和代码页
NTFS 卷标默认用 UTF-16 存储,但 GetVolumeInformationA 会按当前系统 ANSI 代码页(如 GBK)尝试转换,若卷标含中文且系统 locale 不匹配,就会显示为乱码或空字符串。而 GetVolumeInformationW 始终返回原始 UTF-16,更可靠。
应对方式:
- 优先使用
GetVolumeInformationW,自己做 UTF-16 → UTF-8 转换(例如用WideCharToMultiByte(CP_UTF8, ...)) - 不要假设所有卷都有卷标:FAT32 卷标最长 11 字符且不支持 Unicode;exFAT 卷标支持 UTF-16,但部分旧设备写入时可能只存 ASCII
- 某些加密卷(如 BitLocker 挂载后)或网络驱动器(WebDAV、OneDrive 挂载点)可能返回空卷标,这是正常行为,不是代码 bug
GetDriveTypeA 判断是否真挂载,避免无效调用
不是所有逻辑驱动器都对应真实挂载卷。比如 "A:\" 可能是软驱(已淘汰)、"D:\" 可能是 DVD 驱动器但没放光盘、"Z:\" 可能是断开的网络映射。盲目对每个驱动器调用 GetVolumeInformation 会拖慢速度,还可能触发弹窗(如光驱无盘时弹“请插入磁盘”)。
建议流程:
- 先用
GetDriveTypeA("C:\")判断类型:DRIVE_FIXED(本地硬盘)、DRIVE_REMOVABLE(U 盘/SD 卡)、DRIVE_REMOTE(网络驱动器)才值得继续查卷标;DRIVE_NO_ROOT_DIR或DRIVE_UNKNOWN直接跳过 - 对
DRIVE_CDROM类型,仅当GetDriveType返回该值且后续GetVolumeInformation成功时才取卷标;否则大概率是空仓,卷标无意义 - 网络驱动器(
DRIVE_REMOTE)的卷标通常来自服务器共享名,而非远程卷本身的 NTFS 卷标,行为不一致,需单独说明用途


















