2010-05-02 11 views
7

Quando ho lista dischi virtuali all'interno di diskpart:Recupero nome del file del disco virtuale da numero fisso

DISKPART> list vdisk 

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

parte interessante per me qui è il nome del file. Ho cercato di trovare l'equivalente della funzione che mi avrebbe dato il nome del file (sotto la colonna File) se conosco il numero del disco.

Idealmente, vorrei dare "\\ \ PhysicalDrive2?" E mi sarei "C: \ Disk.vhd", come risultato.

Ho già provato:

  1. Utilizzando diskpart e l'analisi in uscita - dal momento che è formato non documentata, può cambiare in qualsiasi momento. Questo non è qualcosa su cui fare affidamento.
  2. Generale VHD API - nessuna funzione prende il numero del disco come parametro.
  3. Microsoft.Storage.Vds.dll - Esistono enumerazioni che attraversano ciascuna unità (ad esempio Service.Providers) ma non esiste alcuna proprietà/funzione che mi fornirà il nome del file di origine. Mentre ora posso essere sicuro che ad es. unità D: è un'unità virtuale, non riesco ancora a sapere quale file .vhd è stato allegato.

Qualche idea quale funzione potrebbe essere?

+0

mi sono imbattuto in questa domanda, mentre la ricerca di un mio progetto. So che la domanda è vecchia ed è stata data risposta alla soddisfazione del richiedente, ma ho pensato che una soluzione API VHD sarebbe stata utile. –

risposta

12

Qui ci sono due soluzioni per recuperare i dischi virtuali sul computer locale e per stampare le loro informazioni. Le due soluzioni dimostrano come utilizzare oggetti COM VDS per accedere a questi dati sia in modo nativo che gestito.

Managed Solution

Ho creare un parziale di interoperabilità COM dal MSDN Documentation e da Windows 7 SDK (principalmente vds.h). Si noti che i wrapper COM sono parziali, il che significa che alcuni metodi devono ancora essere portati.

Di seguito è un'applicazione gestita che utilizza il.NET COM Interop a:

  • caricare il servizio VDS
  • Query per i fornitori di dischi virtuali
  • elencare tutti i dischi virtuali gestite da ogni fornitore:
    • proprietà del disco virtuale dà il suo GUID, il suo percorso completo del driver, la sua dimensione del volume e il suo file del disco (ovvero C:\Disk.vhd).
    • Un disco virtuale può anche essere interrogato come un disco generico e fornisce il suo nome (ad esempio \\?\PhysicalDrive1), il suo nome descrittivo e altre proprietà.

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 
    } 
} 

Native Soluzione

Qui di seguito è un'applicazione nativa che utilizza le interfacce VDS COM per:

  • caricare il servizio VDS
  • Query per i fornitori di dischi virtuali
  • elencare tutti i dischi virtuali gestite da ogni fornitore:
    • proprietà del disco virtuale dà il suo GUID, il suo percorso completo del driver, la sua dimensione del volume e il suo file disco (vale a dire C:\Disk.vhd).
    • Un disco virtuale può anche essere interrogato come un disco generico e fornisce il suo nome (ad esempio \\?\PhysicalDrive1), il suo nome descrittivo e altre proprietà.

#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); 
} 
+0

Lo controllerò. Mi ci vorrà del tempo per riscriverlo in C#. –

+0

Microsoft.Storage.Vds.dll manca IVdsVDisk. Presumo che questo fosse un problema con i miei assegni. –

+0

@Josip: aggiungo una soluzione gestita basata su una parziale interoperabilità COM. –

1

Sembra che sia necessario utilizzare IEnumVdsObject ma non sono sicuro di quale sistema operativo si sta utilizzando?

+0

Il sistema operativo è Windows 7. Verrà controllato. –

+0

Purtroppo, non riesco a trovare nessuna enumerazione che mi dia il file VHD utilizzato per "creare" l'unità. Posso riconoscere VHD nei suoi dati, ma non c'è alcun nome di file in nessuna delle proprietà. –

2

Non esiste un wrapper .NET gestito ufficiale per le API del disco virtuale. Quindi si dispone attualmente di tre opzioni:

  1. eseguire il comando dos e raschiare la risposta console, che non si vuole fare in quanto non è un'API stabile.

  2. Utilizzare Microsoft.Storage.Vds.dll aggiunto in Server 2008. È possibile utilizzare .NET reflector per esaminare l'API. Tuttavia, anche questo non è ufficiale, in quanto non documentato e quindi potrebbe cambiare senza preavviso nei service pack, ecc.

  3. Utilizzare l'API C ufficiale. Questo è ciò che raccomanderei fino a quando una classe wrapper gestita ufficialmente sia rilasciata e documentata. Come notato sopra, lo full API documentation ha tutto ciò di cui hai bisogno. Consiglierei di scrivere una DLL wrapper C semplificata attorno a questa API che fa ciò che ti serve e non di più. Quindi, PInvoke la tua libreria wrapper.

+0

1. Già fatto, non mi piace. 2. Questo sembra molto promettente. Lo proverò. 3. Sfortunatamente, questa funzione accetta tutti il ​​nome del file come input. Per me l'input deve essere il numero del disco. –

+0

Come stai inizialmente ricevendo # disco? – NetMage

+0

Nessun successo con 2. Esistono enumerazioni che passano attraverso ogni unità (ad esempio Service.Providers) ma non esiste alcuna proprietà/funzione che mi darà il nome del file sorgente. Mentre ora posso essere sicuro che ad es. unità D: è un'unità virtuale, non riesco ancora a sapere quale file .vhd è stato allegato. –

0

Non in grado di testare vdisk sulla mia macchina. Ma puoi provare con le query WMI.

es. Posso ottenere le informazioni sulla partizione usando il seguente codice

using System; 
using System.Management; 
using System.Windows.Forms; 

namespace WMISample 
{ 
    public class MyWMIQuery 
    { 
     public static void Main() 
     { 
      try 
      { 
       ManagementObjectSearcher searcher = 
        new ManagementObjectSearcher("root\\CIMV2", 
        "SELECT * FROM Win32_DiskPartition"); 

       foreach (ManagementObject queryObj in searcher.Get()) 
       { 
        Console.WriteLine("-----------------------------------"); 
        Console.WriteLine("Win32_DiskPartition instance"); 
        Console.WriteLine("-----------------------------------"); 
        Console.WriteLine("Access: {0}", queryObj["Access"]); 
        Console.WriteLine("Availability: {0}", queryObj["Availability"]); 
        Console.WriteLine("BlockSize: {0}", queryObj["BlockSize"]); 
        Console.WriteLine("Bootable: {0}", queryObj["Bootable"]); 
        Console.WriteLine("BootPartition: {0}", queryObj["BootPartition"]); 
        Console.WriteLine("Caption: {0}", queryObj["Caption"]); 
        Console.WriteLine("ConfigManagerErrorCode: {0}", queryObj["ConfigManagerErrorCode"]); 
        Console.WriteLine("ConfigManagerUserConfig: {0}", queryObj["ConfigManagerUserConfig"]); 
        Console.WriteLine("CreationClassName: {0}", queryObj["CreationClassName"]); 
        Console.WriteLine("Description: {0}", queryObj["Description"]); 
        Console.WriteLine("DeviceID: {0}", queryObj["DeviceID"]); 
        Console.WriteLine("DiskIndex: {0}", queryObj["DiskIndex"]); 
        Console.WriteLine("ErrorCleared: {0}", queryObj["ErrorCleared"]); 
        Console.WriteLine("ErrorDescription: {0}", queryObj["ErrorDescription"]); 
        Console.WriteLine("ErrorMethodology: {0}", queryObj["ErrorMethodology"]); 
        Console.WriteLine("HiddenSectors: {0}", queryObj["HiddenSectors"]); 
        Console.WriteLine("Index: {0}", queryObj["Index"]); 
        Console.WriteLine("InstallDate: {0}", queryObj["InstallDate"]); 
        Console.WriteLine("LastErrorCode: {0}", queryObj["LastErrorCode"]); 
        Console.WriteLine("Name: {0}", queryObj["Name"]); 
        Console.WriteLine("NumberOfBlocks: {0}", queryObj["NumberOfBlocks"]); 
        Console.WriteLine("PNPDeviceID: {0}", queryObj["PNPDeviceID"]); 

        if(queryObj["PowerManagementCapabilities"] == null) 
         Console.WriteLine("PowerManagementCapabilities: {0}", queryObj["PowerManagementCapabilities"]); 
        else 
        { 
         UInt16[] arrPowerManagementCapabilities = (UInt16[])(queryObj["PowerManagementCapabilities"]); 
         foreach (UInt16 arrValue in arrPowerManagementCapabilities) 
         { 
          Console.WriteLine("PowerManagementCapabilities: {0}", arrValue); 
         } 
        } 
        Console.WriteLine("PowerManagementSupported: {0}", queryObj["PowerManagementSupported"]); 
        Console.WriteLine("PrimaryPartition: {0}", queryObj["PrimaryPartition"]); 
        Console.WriteLine("Purpose: {0}", queryObj["Purpose"]); 
        Console.WriteLine("RewritePartition: {0}", queryObj["RewritePartition"]); 
        Console.WriteLine("Size: {0}", queryObj["Size"]); 
        Console.WriteLine("StartingOffset: {0}", queryObj["StartingOffset"]); 
        Console.WriteLine("Status: {0}", queryObj["Status"]); 
        Console.WriteLine("StatusInfo: {0}", queryObj["StatusInfo"]); 
        Console.WriteLine("SystemCreationClassName: {0}", queryObj["SystemCreationClassName"]); 
        Console.WriteLine("SystemName: {0}", queryObj["SystemName"]); 
        Console.WriteLine("Type: {0}", queryObj["Type"]); 
       } 
      } 
      catch (ManagementException e) 
      { 
       MessageBox.Show("An error occurred while querying for WMI data: " + e.Message); 
      } 
     } 
    } 
} 

Fornisce tutto ciò che riguarda la macchina. Si può provare lo strumento per ottenere spazio dei nomi e classi disponibili sul computer: http://www.microsoft.com/downloads/details.aspx?familyid=2cc30a64-ea15-4661-8da4-55bbc145c30e&displaylang=en

2

P/Invocando la GetStorageDependencyInformation fornirà una soluzione di VHD API strettamente. Mentre questa funzione non richiede un numero di unità come parametro di input, verrà utilizzato un metodo wrapper. Il metodo wrapper converte un numero di unità in una stringa del modulo "\\\\. \\ PhysicalDriveN" che viene passato a CreateFile e l'handle risultante viene passato a GetStorageDependencyInformation. Un simile metodo wrapper richiede un input di una singola lettera di unità char.
Il codice seguente è stato tradotto per C# da un unmanaged example:

using DWORD = System.UInt32; 
using ULONG = System.UInt32; 

using System; 
using System.Collections.Generic; 
using System.Runtime.InteropServices; 
using Microsoft.Win32.SafeHandles; 
using System.IO; 

namespace VhdTest 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      String[] arr; 
      arr = VirtualDisk.GetDependentVolumePaths('e'); 
      arr = VirtualDisk.GetDependentVolumePaths(1); 

     } 
    } 


    class VirtualDisk 
    { 
     #region [ Native ] 

     #region [ Constants ] 
     const DWORD ERROR_INSUFFICIENT_BUFFER = 122; 
     const DWORD ERROR_SUCCESS = 0; 

     const DWORD GENERIC_READ = 0x80000000; 

     const DWORD FILE_SHARE_READ = 1; 
     const DWORD FILE_SHARE_WRITE = 2; 
     const DWORD OPEN_EXISTING = 3; 

     const DWORD FILE_ATTRIBUTE_NORMAL = 0x00000080; 
     const DWORD FILE_FLAG_BACKUP_SEMANTICS = 0x02000000; 
     #endregion 

     #region [ Enums ] 
     [Flags] 
     enum DEPENDENT_DISK_FLAG 
     { 
      DEPENDENT_DISK_FLAG_NONE = 0x00000000, 

      // 
      // Multiple files backing the virtual storage device 
      // 
      DEPENDENT_DISK_FLAG_MULT_BACKING_FILES = 0x00000001, 
      DEPENDENT_DISK_FLAG_FULLY_ALLOCATED = 0x00000002, 
      DEPENDENT_DISK_FLAG_READ_ONLY = 0x00000004, 

      // 
      //Backing file of the virtual storage device is not local to the machine 
      // 
      DEPENDENT_DISK_FLAG_REMOTE = 0x00000008, 

      // 
      // Volume is the system volume 
      // 
      DEPENDENT_DISK_FLAG_SYSTEM_VOLUME = 0x00000010, 

      // 
      // Volume backing the virtual storage device file is the system volume 
      // 
      DEPENDENT_DISK_FLAG_SYSTEM_VOLUME_PARENT = 0x00000020, 
      DEPENDENT_DISK_FLAG_REMOVABLE = 0x00000040, 

      // 
      // Drive letters are not assigned to the volumes 
      // on the virtual disk automatically. 
      // 
      DEPENDENT_DISK_FLAG_NO_DRIVE_LETTER = 0x00000080, 
      DEPENDENT_DISK_FLAG_PARENT = 0x00000100, 

      // 
      // Virtual disk is not attached on the local host 
      // (instead attached on a guest VM for instance) 
      // 
      DEPENDENT_DISK_FLAG_NO_HOST_DISK = 0x00000200, 

      // 
      // Indicates the lifetime of the disk is not tied 
      // to any system handles 
      // 
      DEPENDENT_DISK_FLAG_PERMANENT_LIFETIME = 0x00000400 
     } 

     [Flags] 
     enum GET_STORAGE_DEPENDENCY_FLAG 
     { 
      GET_STORAGE_DEPENDENCY_FLAG_NONE = 0x00000000, 

      // Return information for volumes or disks hosting the volume specified 
      // If not set, returns info about volumes or disks being hosted by 
      // the volume or disk specified 
      GET_STORAGE_DEPENDENCY_FLAG_HOST_VOLUMES = 0x00000001, 
      GET_STORAGE_DEPENDENCY_FLAG_PARENTS = GET_STORAGE_DEPENDENCY_FLAG_HOST_VOLUMES, 
      // The handle provided is to a disk, not volume or file 
      GET_STORAGE_DEPENDENCY_FLAG_DISK_HANDLE = 0x00000002, 

     } 

     enum STORAGE_DEPENDENCY_INFO_VERSION 
     { 
      STORAGE_DEPENDENCY_INFO_VERSION_UNSPECIFIED = 0, 
      STORAGE_DEPENDENCY_INFO_VERSION_1 = 1, 
      STORAGE_DEPENDENCY_INFO_VERSION_2 = 2, 
     } 
     #endregion 

     #region [ Structures ] 
     [StructLayout(LayoutKind.Sequential)] 
     struct STORAGE_DEPENDENCY_INFO_TYPE_1 
     { 
      DEPENDENT_DISK_FLAG DependencyTypeFlags; 
      ULONG ProviderSpecificFlags; 
      VIRTUAL_STORAGE_TYPE VirtualStorageType; 
     } 

     [StructLayout(LayoutKind.Sequential)] 
     struct STORAGE_DEPENDENCY_INFO_TYPE_2 
     { 
      public DEPENDENT_DISK_FLAG DependencyTypeFlags; 
      public ULONG ProviderSpecificFlags; 
      public VIRTUAL_STORAGE_TYPE VirtualStorageType; 
      public ULONG AncestorLevel; 
      public IntPtr DependencyDeviceName; 
      public IntPtr HostVolumeName; 
      public IntPtr DependentVolumeName; 
      public IntPtr DependentVolumeRelativePath; 
     } 

     [StructLayout(LayoutKind.Explicit)] 
     struct STORAGE_DEPENDENCY_INFO_Union 
     { 
      [FieldOffset(0)] 
      STORAGE_DEPENDENCY_INFO_TYPE_1 Version1Entries; 
      [FieldOffset(0)] 
      STORAGE_DEPENDENCY_INFO_TYPE_2 Version2Entries; 
     } 

     [StructLayout(LayoutKind.Sequential)] 
     struct STORAGE_DEPENDENCY_INFO 
     { 
      public STORAGE_DEPENDENCY_INFO_VERSION Version; 
      public ULONG NumberEntries; 
      public STORAGE_DEPENDENCY_INFO_Union Union; 
     } 

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

     #region [ PInvokes ] 
     [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)] 
     public static extern SafeFileHandle CreateFile(string lpFileName, 
      DWORD dwDesiredAccess, 
      DWORD dwShareMode, 
      IntPtr lpSecurityAttributes, 
      DWORD dwCreationDisposition, 
      DWORD dwFlagsAndAttributes, 
      IntPtr hTemplateFile); 


     [DllImport("virtdisk.dll", SetLastError = true, CharSet = CharSet.Unicode)] 
     static extern DWORD GetStorageDependencyInformation(SafeHandle ObjectHandle, 
      GET_STORAGE_DEPENDENCY_FLAG Flags, 
      ULONG StorageDependencyInfoSize, 
      IntPtr StorageDependencyInfo, 
      ref ULONG SizeUsed); 
     #endregion 

     #endregion 

     #region [ Managed Methods ] 
     public static String[] GetDependentVolumePaths(char driveLetter) 
     { 
      driveLetter = Char.ToUpper(driveLetter); 
      if (driveLetter < 'A' || driveLetter > 'Z') 
      { 
       String paramName = "driveLetter"; 
       String message = "Drive letter must fall in range [a-zA-Z]"; 
       throw new ArgumentOutOfRangeException(paramName, message); 
      } 
      String fileName = String.Format(@"\\.\{0}:\", driveLetter); 
      return getDependentVolumePaths(fileName); 
     } 

     public static String[] GetDependentVolumePaths(UInt32 driveNumber) 
     { 
      // TODO: Per SO, isn't max drive 15? 
      // http://stackoverflow.com/questions/327718/how-to-list-physical-disks 
      if (driveNumber > 9) 
      { 
       String paramName = "driveNumber"; 
       String message = "Drive number must be <= 9"; 
       throw new ArgumentOutOfRangeException(paramName, message); 
      } 
      String fileName = String.Format(@"\\.\PhysicalDrive{0}", driveNumber); 
      return getDependentVolumePaths(fileName); 
     } 

     static unsafe String[] getDependentVolumePaths(String fileName) 
     { 
      DWORD dwDesiredAccess = GENERIC_READ; 
      DWORD dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; 
      DWORD dwCreationDisposition = OPEN_EXISTING; 
      DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS; 

      SafeHandle driveHandle = null; 
      STORAGE_DEPENDENCY_INFO info = new STORAGE_DEPENDENCY_INFO(); 
      info.Version = STORAGE_DEPENDENCY_INFO_VERSION.STORAGE_DEPENDENCY_INFO_VERSION_2; 
      IntPtr ptr; 

      try 
      { 
       driveHandle = CreateFile(fileName, 
        dwDesiredAccess, //GENERIC_READ, 
        dwShareMode, 
        IntPtr.Zero, 
        dwCreationDisposition, 
        dwFlagsAndAttributes, 
        IntPtr.Zero); 
       if (driveHandle.IsInvalid) 
       { 
        return null; 
       } 

       GET_STORAGE_DEPENDENCY_FLAG flags = GET_STORAGE_DEPENDENCY_FLAG.GET_STORAGE_DEPENDENCY_FLAG_NONE; 
       flags |= GET_STORAGE_DEPENDENCY_FLAG.GET_STORAGE_DEPENDENCY_FLAG_PARENTS; 
       if (fileName.ToUpper().Contains("PHYSICAL")) 
        flags |= GET_STORAGE_DEPENDENCY_FLAG.GET_STORAGE_DEPENDENCY_FLAG_DISK_HANDLE; 

       DWORD infoSize = (DWORD)Marshal.SizeOf(info); 

       byte[] infoByteArray; 
       DWORD cbSize = 0; 
       DWORD opStatus; 

       #region [ Pull STORAGE_DEPENDENCY_INFO into byte array ] 
       infoByteArray = new byte[infoSize]; 
       fixed (byte* p1 = infoByteArray) 
       { 
        ptr = (IntPtr)p1; 
        Marshal.StructureToPtr(info, ptr, true); 
        opStatus = GetStorageDependencyInformation(driveHandle, flags, infoSize, ptr, ref cbSize); 

        if (opStatus == ERROR_INSUFFICIENT_BUFFER) 
        { 
         infoSize = cbSize; 
         cbSize = 0; 

         infoByteArray = new byte[infoSize]; 
         fixed (byte* p2 = infoByteArray) 
         { 
          ptr = (IntPtr)p2; 
          Marshal.StructureToPtr(info, ptr, true); 
          opStatus = GetStorageDependencyInformation(driveHandle, flags, infoSize, ptr, ref cbSize); 
         } 
        } 

       } 

       #endregion 
       if (opStatus != ERROR_SUCCESS) 
       { 
        // 
        // This is most likely due to the disk not being a mounted VHD. 
        // 
        return null; 
       } 
      } 
      finally 
      { 
       if (driveHandle != null && !driveHandle.IsInvalid && !driveHandle.IsClosed) 
       { 
        driveHandle.Close(); 
       } 
      } 

      List<String> pathList = new List<String>(); 
      info = (STORAGE_DEPENDENCY_INFO)Marshal.PtrToStructure(ptr, typeof(STORAGE_DEPENDENCY_INFO)); 
      //STORAGE_DEPENDENCY_INFO_TYPE_2 sdi2 = new STORAGE_DEPENDENCY_INFO_TYPE_2(); 
      STORAGE_DEPENDENCY_INFO_TYPE_2* p = (STORAGE_DEPENDENCY_INFO_TYPE_2*)&info.Union; 
      for (DWORD i = 0; i < info.NumberEntries; i++, p++) 
      { 
       ptr = (IntPtr)p; 
       STORAGE_DEPENDENCY_INFO_TYPE_2 sdi2 = (STORAGE_DEPENDENCY_INFO_TYPE_2)Marshal.PtrToStructure(ptr, typeof(STORAGE_DEPENDENCY_INFO_TYPE_2)); 
       String str1 = Marshal.PtrToStringUni(sdi2.DependencyDeviceName); 
       String str2 = Marshal.PtrToStringUni(sdi2.HostVolumeName); 
       String str3 = Marshal.PtrToStringUni(sdi2.DependentVolumeName); 
       String relativePath = Marshal.PtrToStringUni(sdi2.DependentVolumeRelativePath); 
       String fullPath = Path.GetFullPath(relativePath); 
       pathList.Add(fullPath); 
      } 
      return pathList.ToArray(); 
     } 
     #endregion 
    } 

}