代码之家  ›  专栏  ›  技术社区  ›  Josip Medved

从磁盘号检索虚拟磁盘文件名

  •  7
  • Josip Medved  · 技术社区  · 15 年前

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

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

    对我来说有趣的是文件名。我试图找到一个等价的函数,如果我知道磁盘号,它会给我文件名(在文件列下)。

    理想情况下,我会付出” \?\物理驱动器2 “我会得到” C:\磁盘.vhd “因此。

    我已经试过了:

    1. 使用diskpart并解析输出-因为它是未记录的格式,所以它可以随时更改。这不是我可以依赖的。
    2. 总则 VHD API -没有函数将磁盘号作为参数。
    3. Microsoft.storage.vds.dll-每个驱动器中都有枚举(例如service.providers),但没有属性/函数可以提供源文件的名称。虽然我现在可以确定驱动器d:是虚拟驱动器,但我仍然不知道附加了哪个.vhd文件。

    你知道那是什么功能吗?

    5 回复  |  直到 15 年前
        1
  •  12
  •   Laurent Etiemble    15 年前

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

    托管解决方案

    我已经从 MSDN Documentation 从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接口的本机应用程序:

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

    #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);
    }
    
        2
  •  2
  •   fmark    15 年前

    虚拟磁盘API没有官方托管的.NET包装器。所以你现在有三个选择:

    1. 运行dos命令并删除控制台响应,这是您不想做的,因为它不是一个稳定的api。

    2. 使用 Microsoft.Storage.Vds.dll 这是在服务器2008中添加的。你可以用 .NET reflector 检查api。但是,这也是非官方的,因为它没有文档记录,因此在服务包等中可能会在没有警告的情况下更改。

    3. 使用官方的C API . 在正式的托管包装类被发布和记录之前,这是我的建议。如上所述, full API documentation 有你需要的一切。我建议在这个api周围编写一个简化的c包装器dll,它可以满足您的需要,而不需要更多。然后,pinvoke你的包装库。

        3
  •  2
  •   LJ VanKuiken    12 年前

    p/调用 GetStorageDependencyInformation 将提供一个严格的 VHD API 解决方案。虽然此函数不将驱动器号作为输入参数,但包装器方法将。wrapper方法将驱动器号转换为以下形式的字符串“ \\\\.\\物理驱动 “传递给 CreateFile 结果句柄被传递给 GetStorageDependencyInformation . 类似的包装方法将接受单个 char 驱动器号。
    以下代码从 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
        }
    
    }
    
        4
  •  1
  •   NetMage    15 年前

    似乎你需要使用IEnumvdsObject,但我不确定你在使用什么操作系统?

        5
  •  0
  •   Sachin Chavan bortzmeyer    15 年前

    无法在我的计算机上测试VDisk。但您可以尝试使用wmi查询。

    我可以用下面的代码得到分区信息

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

    它提供了与你的机器相关的一切。 您可以尝试使用该工具获取计算机上可用的命名空间和类: http://www.microsoft.com/downloads/details.aspx?familyid=2cc30a64-ea15-4661-8da4-55bbc145c30e&displaylang=en