gpt4 book ai didi

c# - 从磁盘号检索虚拟磁盘文件名

转载 作者:太空狗 更新时间:2023-10-29 19:57:45 26 4
gpt4 key购买 nike

当我在 diskpart 中列出虚拟磁盘时:

DISKPART> list vdisk

VDisk ### Disk ### State Type File
--------- -------- -------------------- --------- ----
VDisk 0 Disk 2 Attached not open Fixed C:\Disk.vhd

对我来说有趣的部分是文件名。如果我知道磁盘编号,我试图找到可以给我文件名(在"file"列下)的等效函数。

理想情况下,我会给出“\\?\PhysicalDrive2”,结果我会得到“C:\Disk.vhd”。

我已经试过了:

  1. 使用 diskpart 和解析输出——因为它是未记录的格式,它可以随时更改。这不是我会依赖的东西。
  2. 一般 VHD API - 没有函数将磁盘号作为参数。
  3. Microsoft.Storage.Vds.dll - 每个驱动器都有枚举(例如 Service.Providers),但没有属性/函数可以给我源文件的名称。虽然我现在可以确定,例如驱动器 D: 是虚拟驱动器,我仍然不知道附加了哪个 .vhd 文件。

知道可能是哪个函数吗?

最佳答案

这里有两个解决方案来检索本地机器上的虚拟磁盘并打印它们的信息。这两个解决方案演示了如何使用 VDS COM 对象以 native 方式和托管方式访问这些数据。

托管解决方案

我已经从 MSDN Documentation 创建了部分 COM Interop以及来自 Windows 7 SDK(主要是 vds.h)。请注意,COM 包装器是部分的,这意味着某些方法尚未移植。

下面是一个托管应用程序,它使用 .NET COM 互操作来:

  • 加载 VDS 服务
  • 查询虚拟磁盘供应商
  • 列出每个提供商处理的所有虚拟磁盘:
    • 虚拟磁盘的属性提供了它的 GUID、它的完整驱动程序路径、它的卷大小和它的磁盘文件(即 C:\Disk.vhd)。
    • 虚拟磁盘也可以作为通用磁盘进行查询,并提供其名称(即 \\?\PhysicalDrive1)、友好名称和其他属性。

using System;
using System.Runtime.InteropServices;

namespace VDiskDumper
{
class Program
{
static void Main(string[] args)
{
// Create the service loader
VdsServiceLoader loaderClass = new VdsServiceLoader();
IVdsServiceLoader loader = (IVdsServiceLoader)loaderClass;
Console.WriteLine("Got Loader");

// Load the service
IVdsService service;
loader.LoadService(null, out service);
Console.WriteLine("Got Service");

// Wait for readyness
service.WaitForServiceReady();
Console.WriteLine("Service is ready");

// Query for vdisk providers
IEnumVdsObject providerEnum;
service.QueryProviders(VDS_QUERY_PROVIDER_FLAG.VDS_QUERY_VIRTUALDISK_PROVIDERS, out providerEnum);
Console.WriteLine("Got Providers");

// Iterate
while (true)
{
uint fetched;
object unknown;
providerEnum.Next(1, out unknown, out fetched);

if (fetched == 0) break;

// Cast to the required type
IVdsVdProvider provider = (IVdsVdProvider)unknown;
Console.WriteLine("Got VD Provider");

Dump(provider);
}

Console.ReadKey();
}

private static void Dump(IVdsVdProvider provider)
{
// Query for the vdisks
IEnumVdsObject diskEnum;
provider.QueryVDisks(out diskEnum);
Console.WriteLine("Got VDisks");

// Iterate
while (true)
{
uint fetched;
object unknown;
diskEnum.Next(1, out unknown, out fetched);

if (fetched == 0) break;

// Cast to the required type
IVdsVDisk vDisk = (IVdsVDisk)unknown;

// Get the vdisk properties
VDS_VDISK_PROPERTIES vdiskProperties;
vDisk.GetProperties(out vdiskProperties);

Console.WriteLine("-> VDisk Id=" + vdiskProperties.Id);
Console.WriteLine("-> VDisk Device Name=" + vdiskProperties.pDeviceName);
Console.WriteLine("-> VDisk Path=" + vdiskProperties.pPath);

// Get the associated disk
IVdsDisk disk;
provider.GetDiskFromVDisk(vDisk, out disk);

// Get the disk properties
VDS_DISK_PROP diskProperties;
disk.GetProperties(out diskProperties);

Console.WriteLine("-> Disk Name=" + diskProperties.pwszName);
Console.WriteLine("-> Disk Friendly=" + diskProperties.pwszFriendlyName);
}
}
}

[ComImport, Guid("118610b7-8d94-4030-b5b8-500889788e4e"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IEnumVdsObject
{
void Next(uint numberOfObjects, [MarshalAs(UnmanagedType.IUnknown)] out object objectUnk, out uint numberFetched);
void Skip(uint NumberOfObjects);
void Reset();
void Clone(out IEnumVdsObject Enum);
}

[ComImport, Guid("07e5c822-f00c-47a1-8fce-b244da56fd06"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IVdsDisk
{
void GetProperties(out VDS_DISK_PROP diskProperties);
void GetPack(); // Unported method
void GetIdentificationData(IntPtr lunInfo);
void QueryExtents(); // Unported method
void slot4();
void SetFlags(); // Unported method
void ClearFlags(); // Unported method
}

[ComImport, Guid("0818a8ef-9ba9-40d8-a6f9-e22833cc771e"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IVdsService
{
[PreserveSig]
int IsServiceReady();
[PreserveSig]
int WaitForServiceReady();
void GetProperties(); // Unported method
void QueryProviders(VDS_QUERY_PROVIDER_FLAG mask, out IEnumVdsObject providers);
void QueryMaskedDisks(out IEnumVdsObject disks);
void QueryUnallocatedDisks(out IEnumVdsObject disks);
void GetObject(); // Unported method
void QueryDriveLetters(); // Unported method
void QueryFileSystemTypes(out IntPtr fileSystemTypeProps, out uint numberOfFileSystems);
void Reenumerate();
void Refresh();
void CleanupObsoleteMountPoints();
void Advise(); // Unported method
void Unadvise(); // Unported method
void Reboot();
void SetFlags(); // Unported method
void ClearFlags(); // Unported method
}

[ComImport, Guid("e0393303-90d4-4a97-ab71-e9b671ee2729"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IVdsServiceLoader
{
void LoadService([In, MarshalAs(UnmanagedType.LPWStr)] string machineName, out IVdsService vdsService);
}

[ComImport, Guid("1e062b84-e5e6-4b4b-8a25-67b81e8f13e8"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IVdsVDisk
{
void Open(); // Unported method
void GetProperties(out VDS_VDISK_PROPERTIES pDiskProperties);
void GetHostVolume(); // Unported method
void GetDeviceName(); // Unported method
}

[ComImport, Guid("b481498c-8354-45f9-84a0-0bdd2832a91f"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IVdsVdProvider
{
void QueryVDisks(out IEnumVdsObject ppEnum);
void CreateVDisk(); // Unported method
void AddVDisk(); // Unported method
void GetDiskFromVDisk(IVdsVDisk pVDisk, out IVdsDisk ppDisk);
void GetVDiskFromDisk(IVdsDisk pDisk, out IVdsVDisk ppVDisk);
}

[ComImport, Guid("9c38ed61-d565-4728-aeee-c80952f0ecde")]
public class VdsServiceLoader
{
}

[StructLayout(LayoutKind.Explicit)]
public struct Signature
{
[FieldOffset(0)]
public uint dwSignature;
[FieldOffset(0)]
public Guid DiskGuid;
}

[StructLayout(LayoutKind.Sequential)]
public struct VDS_DISK_PROP
{
public Guid Id;
public VDS_DISK_STATUS Status;
public VDS_LUN_RESERVE_MODE ReserveMode;
public VDS_HEALTH health;
public uint dwDeviceType;
public uint dwMediaType;
public ulong ullSize;
public uint ulBytesPerSector;
public uint ulSectorsPerTrack;
public uint ulTracksPerCylinder;
public uint ulFlags;
public VDS_STORAGE_BUS_TYPE BusType;
public VDS_PARTITION_STYLE PartitionStyle;
public Signature dwSignature;
[MarshalAs(UnmanagedType.LPWStr)]
public string pwszDiskAddress;
[MarshalAs(UnmanagedType.LPWStr)]
public string pwszName;
[MarshalAs(UnmanagedType.LPWStr)]
public string pwszFriendlyName;
[MarshalAs(UnmanagedType.LPWStr)]
public string pwszAdaptorName;
[MarshalAs(UnmanagedType.LPWStr)]
public string pwszDevicePath;
}

[StructLayout(LayoutKind.Sequential)]
public struct VIRTUAL_STORAGE_TYPE
{
public uint DeviceId;
public Guid VendorId;
}

[StructLayout(LayoutKind.Sequential)]
public struct VDS_VDISK_PROPERTIES
{
public Guid Id;
public VDS_VDISK_STATE State;
public VIRTUAL_STORAGE_TYPE VirtualDeviceType;
public ulong VirtualSize;
public ulong PhysicalSize;
[MarshalAs(UnmanagedType.LPWStr)]
public String pPath;
[MarshalAs(UnmanagedType.LPWStr)]
public String pDeviceName;
public DEPENDENT_DISK_FLAG DiskFlag;
public bool bIsChild;
[MarshalAs(UnmanagedType.LPWStr)]
public String pParentPath;
}

public enum DEPENDENT_DISK_FLAG
{
DEPENDENT_DISK_FLAG_NONE = 0x00000000,
DEPENDENT_DISK_FLAG_MULT_BACKING_FILES = 0x00000001,
DEPENDENT_DISK_FLAG_FULLY_ALLOCATED = 0x00000002,
DEPENDENT_DISK_FLAG_READ_ONLY = 0x00000004,
DEPENDENT_DISK_FLAG_REMOTE = 0x00000008,
DEPENDENT_DISK_FLAG_SYSTEM_VOLUME = 0x00000010,
DEPENDENT_DISK_FLAG_SYSTEM_VOLUME_PARENT = 0x00000020,
DEPENDENT_DISK_FLAG_REMOVABLE = 0x00000040,
DEPENDENT_DISK_FLAG_NO_DRIVE_LETTER = 0x00000080,
DEPENDENT_DISK_FLAG_PARENT = 0x00000100,
DEPENDENT_DISK_FLAG_NO_HOST_DISK = 0x00000200,
DEPENDENT_DISK_FLAG_PERMANENT_LIFETIME = 0x00000400,
}

public enum VDS_DISK_STATUS
{
VDS_DS_UNKNOWN = 0,
VDS_DS_ONLINE = 1,
VDS_DS_NOT_READY = 2,
VDS_DS_NO_MEDIA = 3,
VDS_DS_FAILED = 5,
VDS_DS_MISSING = 6,
VDS_DS_OFFLINE = 4
}

public enum VDS_HEALTH
{
VDS_H_UNKNOWN = 0,
VDS_H_HEALTHY = 1,
VDS_H_REBUILDING = 2,
VDS_H_STALE = 3,
VDS_H_FAILING = 4,
VDS_H_FAILING_REDUNDANCY = 5,
VDS_H_FAILED_REDUNDANCY = 6,
VDS_H_FAILED_REDUNDANCY_FAILING = 7,
VDS_H_FAILED = 8,
VDS_H_REPLACED = 9,
VDS_H_PENDING_FAILURE = 10,
VDS_H_DEGRADED = 11
}

public enum VDS_LUN_RESERVE_MODE
{
VDS_LRM_NONE = 0,
VDS_LRM_EXCLUSIVE_RW = 1,
VDS_LRM_EXCLUSIVE_RO = 2,
VDS_LRM_SHARED_RO = 3,
VDS_LRM_SHARED_RW = 4
}

public enum VDS_PARTITION_STYLE
{
VDS_PST_UNKNOWN = 0,
VDS_PST_MBR = 1,
VDS_PST_GPT = 2
}

public enum VDS_QUERY_PROVIDER_FLAG
{
VDS_QUERY_SOFTWARE_PROVIDERS = 0x1,
VDS_QUERY_HARDWARE_PROVIDERS = 0x2,
VDS_QUERY_VIRTUALDISK_PROVIDERS = 0x4
}

public enum VDS_STORAGE_BUS_TYPE
{
VDSBusTypeUnknown = 0,
VDSBusTypeScsi = 0x1,
VDSBusTypeAtapi = 0x2,
VDSBusTypeAta = 0x3,
VDSBusType1394 = 0x4,
VDSBusTypeSsa = 0x5,
VDSBusTypeFibre = 0x6,
VDSBusTypeUsb = 0x7,
VDSBusTypeRAID = 0x8,
VDSBusTypeiScsi = 0x9,
VDSBusTypeSas = 0xa,
VDSBusTypeSata = 0xb,
VDSBusTypeSd = 0xc,
VDSBusTypeMmc = 0xd,
VDSBusTypeMax = 0xe,
VDSBusTypeFileBackedVirtual = 0xf,
VDSBusTypeMaxReserved = 0x7f
}

public enum VDS_VDISK_STATE
{
VDS_VST_UNKNOWN = 0,
VDS_VST_ADDED,
VDS_VST_OPEN,
VDS_VST_ATTACH_PENDING,
VDS_VST_ATTACHED_NOT_OPEN,
VDS_VST_ATTACHED,
VDS_VST_DETACH_PENDING,
VDS_VST_COMPACTING,
VDS_VST_MERGING,
VDS_VST_EXPANDING,
VDS_VST_DELETED,
VDS_VST_MAX
}
}

原生解决方案

下面是使用 VDS COM 接口(interface)的 native 应用程序:

  • 加载 VDS 服务
  • 查询虚拟磁盘供应商
  • 列出每个提供商处理的所有虚拟磁盘:
    • 虚拟磁盘的属性提供了它的 GUID、它的完整驱动程序路径、它的卷大小和它的磁盘文件(即 C:\Disk.vhd)。
    • 虚拟磁盘也可以作为通用磁盘进行查询,并提供其名称(即 \\?\PhysicalDrive1)、友好名称和其他属性。

#include "initguid.h"
#include "vds.h"
#include <stdio.h>

#pragma comment( lib, "ole32.lib" )
#pragma comment( lib, "rpcrt4.lib" )

// Simple macro to release non-null interfaces.
#define _SafeRelease(x) {if (NULL != x) { x->Release(); x = NULL; } }

void exploreVDiskProvider(IVdsVdProvider *pVdProvider);

int __cdecl main(void)
{
HRESULT hResult;
ULONG ulFetched = 0;
BOOL bDone = FALSE;

IVdsServiceLoader *pLoader = NULL;
IVdsService *pService = NULL;
IEnumVdsObject *pProviderEnum = NULL;
IUnknown *pUnknown = NULL;
IVdsVdProvider *pVdProvider = NULL;

// Initialize COM
hResult = CoInitialize(NULL);
if (FAILED(hResult)) goto bail;

// For this, get a pointer to the VDS Loader
hResult = CoCreateInstance(CLSID_VdsLoader,
NULL,
CLSCTX_LOCAL_SERVER,
IID_IVdsServiceLoader,
(void **) &pLoader);
if (FAILED(hResult)) goto bail;

printf("Loading VDS Service...\n");

// Launch the VDS service.
hResult = pLoader->LoadService(NULL, &pService);

// We're done with the Loader interface at this point.
_SafeRelease(pLoader);

if (FAILED(hResult)) goto bail;

// Wait for service to be ready
hResult = pService->WaitForServiceReady();
if (FAILED(hResult)) goto bail;

printf("VDS Service Loaded\n");

// Query for virtual disk providers
hResult = pService->QueryProviders(VDS_QUERY_VIRTUALDISK_PROVIDERS, &pProviderEnum);
if (FAILED(hResult)) goto bail;

printf("Querying providers...\n");

// Iterate over virtual disk providers
while(1)
{
ulFetched = 0;
hResult = pProviderEnum->Next(1, &pUnknown, &ulFetched);
if (FAILED(hResult)) {
break;
}
if (hResult == S_FALSE) {
break;
}

// Cast the current value to a virtual disk provider
hResult = pUnknown->QueryInterface(IID_IVdsVdProvider, (void **) &pVdProvider);
if (FAILED(hResult)) goto bail;

printf("VDS Virtual Disk Provider Found\n");

exploreVDiskProvider(pVdProvider);

_SafeRelease(pVdProvider);

_SafeRelease(pUnknown);
}

getchar();
return 0;

bail:
printf("Failed hr=%x\n", hResult);
return 1;
}

void exploreVDiskProvider(IVdsVdProvider *pVdProvider) {
HRESULT hResult;
ULONG ulFetched = 0;

IEnumVdsObject *pVDiskEnum = NULL;
IVdsVDisk *pVDisk = NULL;
IUnknown *pUnknown = NULL;
IVdsVolume *pVolume = NULL;
VDS_VDISK_PROPERTIES vdiskProperties = { 0 };
TCHAR *uuid = NULL;
IVdsDisk *pDisk = NULL;
VDS_DISK_PROP diskProperties = { 0 };

// Query the disks handled by the provider
hResult = pVdProvider->QueryVDisks(&pVDiskEnum);
if (FAILED(hResult)) goto bail;

printf("Querying virtual disks...\n");

// Iterate over virtual disks
while(1)
{
ulFetched = 0;
hResult = pVDiskEnum->Next(1, &pUnknown, &ulFetched);
if (hResult == S_FALSE) {
break;
}

if (FAILED(hResult)) goto bail;

// Cast the current value to a disk
hResult = pUnknown->QueryInterface(IID_IVdsVDisk, (void **) &pVDisk);
if (FAILED(hResult)) goto bail;

printf("Virtual disk Found\n");

// Get the disk's properties and display some of them
hResult = pVDisk->GetProperties(&vdiskProperties);
if (FAILED(hResult)) goto bail;

// Convert the GUID to a string
UuidToString(&vdiskProperties.Id, (RPC_WSTR *) &uuid);

// Dump some properties
printf("-> Disk Id=%ws\n", uuid);
printf("-> Disk Device Name=%ws\n", vdiskProperties.pDeviceName);
printf("-> Disk Path=%ws\n", vdiskProperties.pPath);

// Get the disk instance from the virtual disk
hResult = pVdProvider->GetDiskFromVDisk(pVDisk, &pDisk);
if (FAILED(hResult)) goto bail;

_SafeRelease(pVDisk);

_SafeRelease(pUnknown);

// Get the disk's properties and display some of them
hResult = pDisk->GetProperties(&diskProperties);
if (FAILED(hResult)) goto bail;

printf("-> Disk Name=%ws\n", diskProperties.pwszName);
printf("-> Disk Friendly Name=%ws\n", diskProperties.pwszFriendlyName);
}

return;

bail:
printf("Failed hr=%x\n", hResult);
}

关于c# - 从磁盘号检索虚拟磁盘文件名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2755458/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com