如何在Windows中获取已挂载VHD/VHDX路径?需支持Windows 8系统
获取Windows 8及以上系统中挂载的VHD/VHDX路径的替代方案
由于GetAllAttachedVirtualDiskPhysicalPaths仅在Windows 8.1及更高版本可用,我这里提供几个兼容Windows 8的可靠方案,覆盖脚本和原生开发场景:
方法1:PowerShell + DiskPart(最简便的临时查询方案)
DiskPart工具从Windows 7开始就支持list vdisk命令,我们可以通过解析它的输出来提取已挂载的VHD/VHDX路径。这个方法不需要编译代码,直接在PowerShell中运行即可:
# 创建临时DiskPart脚本 $tempScript = Join-Path $env:TEMP "ListMountedVHDs.txt" "list vdisk" | Out-File $tempScript -Encoding ASCII # 执行DiskPart并捕获输出 $diskpartOutput = diskpart /s $tempScript # 解析输出,筛选已挂载的VHD路径 $mountedVHDs = $diskpartOutput | Where-Object { $_ -match "^VHD PATH:\s+(.*)\s+MOUNTED" } | ForEach-Object { $matches[1].Trim() } # 打印结果 Write-Host "已挂载的VHD/VHDX路径:" $mountedVHDs # 清理临时文件 Remove-Item $tempScript -Force
优点:零依赖,操作简单;缺点:依赖DiskPart的输出格式,若微软未来调整输出结构可能失效,但短期兼容性没问题。
方法2:PowerShell调用Virtual Disk API(更可靠的自动化方案)
如果需要更稳定的实现,可以通过PowerShell的P/Invoke直接调用Windows原生的Virtual Disk API,避免依赖输出格式:
Add-Type @" using System; using System.Runtime.InteropServices; public class VirtualDiskUtils { // 定义虚拟磁盘信息结构体(仅保留需要的字段) [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] public struct VIRTUAL_DISK_INFORMATION { public uint Version; public uint VirtualDiskId; public string VirtualDiskPath; } // 导入Virtual Disk API函数 [DllImport("virtdisk.dll", CharSet = CharSet.Unicode)] public static extern int OpenVirtualDisk( ref IntPtr VirtualDiskHandle, string Path, uint AccessMask, uint OpenOptions, IntPtr Parameters, IntPtr Result ); [DllImport("virtdisk.dll", CharSet = CharSet.Unicode)] public static extern int GetVirtualDiskInformation( IntPtr VirtualDiskHandle, ref uint VirtualDiskInformationSize, ref VIRTUAL_DISK_INFORMATION VirtualDiskInformation, IntPtr SizeUsed ); [DllImport("virtdisk.dll")] public static extern int CloseVirtualDisk( IntPtr VirtualDiskHandle, uint CloseOptions, IntPtr Parameters ); } "@ # 获取系统中所有物理磁盘 $allDisks = Get-WmiObject -Class Win32_DiskDrive $mountedVHDs = @() foreach ($disk in $allDisks) { $devicePath = $disk.DeviceID # 格式如 \\.\PhysicalDriveX $vhdHandle = [IntPtr]::Zero $infoSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type][VirtualDiskUtils+VIRTUAL_DISK_INFORMATION]) $vhdInfo = New-Object VirtualDiskUtils+VIRTUAL_DISK_INFORMATION $vhdInfo.Version = 1 # 使用VIRTUAL_DISK_INFORMATION_VERSION_1 # 尝试将磁盘作为虚拟磁盘打开 $openResult = [VirtualDiskUtils]::OpenVirtualDisk([ref]$vhdHandle, $devicePath, 0x00000001, 0, [IntPtr]::Zero, [IntPtr]::Zero) if ($openResult -eq 0) { # 获取虚拟磁盘信息 $infoResult = [VirtualDiskUtils]::GetVirtualDiskInformation($vhdHandle, [ref]$infoSize, [ref]$vhdInfo, [IntPtr]::Zero) if ($infoResult -eq 0 -and ![string]::IsNullOrEmpty($vhdInfo.VirtualDiskPath)) { $mountedVHDs += $vhdInfo.VirtualDiskPath } # 关闭虚拟磁盘句柄 [VirtualDiskUtils]::CloseVirtualDisk($vhdHandle, 0, [IntPtr]::Zero) } } # 输出结果 Write-Host "已挂载的VHD/VHDX路径:" $mountedVHDs
这个方法直接调用官方API,兼容性和稳定性更好,适合集成到自动化脚本中。
方法3:C++原生代码(适合桌面应用开发)
如果是开发C++桌面应用,可以直接使用Virtual Disk API遍历所有磁盘,判断是否为虚拟磁盘并提取路径:
#include <windows.h> #include <virtdisk.h> #include <vector> #include <string> #include <iostream> #pragma comment(lib, "virtdisk.lib") std::vector<std::wstring> GetMountedVirtualDiskPaths() { std::vector<std::wstring> vhdPaths; // 遍历所有物理磁盘 DWORD diskNumber = 0; while (true) { WCHAR devicePath[256]; swprintf_s(devicePath, L"\\\\.\\PhysicalDrive%d", diskNumber); // 打开物理磁盘 HANDLE hPhysicalDisk = CreateFileW( devicePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr ); if (hPhysicalDisk == INVALID_HANDLE_VALUE) { if (GetLastError() == ERROR_FILE_NOT_FOUND) { break; // 遍历完所有磁盘 } diskNumber++; continue; } // 尝试将磁盘作为虚拟磁盘打开 VIRTUAL_DISK_HANDLE vhdHandle = nullptr; OPEN_VIRTUAL_DISK_PARAMETERS openParams = {0}; openParams.Version = OPEN_VIRTUAL_DISK_VERSION_1; DWORD result = OpenVirtualDisk( &vhdHandle, devicePath, VIRTUAL_DISK_ACCESS_READ, OPEN_VIRTUAL_DISK_FLAG_NONE, &openParams, nullptr ); if (result == ERROR_SUCCESS) { // 获取虚拟磁盘信息 DWORD infoSize = sizeof(VIRTUAL_DISK_INFORMATION); VIRTUAL_DISK_INFORMATION vhdInfo = {0}; vhdInfo.Version = VIRTUAL_DISK_INFORMATION_VERSION_1; result = GetVirtualDiskInformation( vhdHandle, &infoSize, &vhdInfo, nullptr ); if (result == ERROR_SUCCESS && vhdInfo.VirtualDiskPath != nullptr) { vhdPaths.emplace_back(vhdInfo.VirtualDiskPath); } // 关闭虚拟磁盘句柄 CloseVirtualDisk(vhdHandle, 0, nullptr); } CloseHandle(hPhysicalDisk); diskNumber++; } return vhdPaths; } int main() { auto mountedVHDs = GetMountedVirtualDiskPaths(); std::wcout << L"已挂载的VHD/VHDX路径:\n"; for (const auto& path : mountedVHDs) { std::wcout << path << L"\n"; } return 0; }
编译时需要链接virtdisk.lib,这个方案完全基于Windows原生API,性能和兼容性最佳,适合需要嵌入到应用中的场景。
内容的提问来源于stack exchange,提问作者Isso
相关产品推荐
相关产品推荐

