获取未知文件格式的磁盘和/或驱动器的大小,C#.NET Framework?

获取未知文件格式的磁盘和/或驱动器的大小,C#.NET Framework?,c#,.net,windows,disk,diskspace,C#,.net,Windows,Disk,Diskspace,我希望能够以编程方式获取物理磁盘的大小,或者物理磁盘的逻辑驱动器的大小 在正常情况下,获取逻辑驱动器大小很容易。但是,对于我正在使用的磁盘,我故意将原始数据写入其中,因此它应该具有未知的驱动器格式 由于Windows不知道驱动器格式,Windows驱动器属性和.NET Framework的DriveInfo无法告诉我组成此物理磁盘的逻辑驱动器的大小。在DriveInfo foo中,我所说的格式是指foo.DriveFormat,foo.IsReady为false,foo.TotalSize触发异

我希望能够以编程方式获取物理磁盘的大小,或者物理磁盘的逻辑驱动器的大小

在正常情况下,获取逻辑驱动器大小很容易。但是,对于我正在使用的磁盘,我故意将原始数据写入其中,因此它应该具有未知的驱动器格式

由于Windows不知道驱动器格式,Windows驱动器属性和.NET Framework的DriveInfo无法告诉我组成此物理磁盘的逻辑驱动器的大小。在DriveInfo foo中,我所说的格式是指foo.DriveFormat,foo.IsReady为false,foo.TotalSize触发异常。只需右键单击驱动器并通过Windows的“属性”选项手动获取大小,驱动器大小将显示0字节

在Windows 7系统上,最好使用C#,使用.NET Framework 4.0或更早版本,如果与物理磁盘关联的逻辑驱动器没有已知的文件结构,我如何了解物理磁盘或组成物理磁盘的逻辑驱动器的大小? 具体来说,物理磁盘大小更适合我的目的


我知道通常有一种方法可以使用Windows 7,正如我所看到的,应用程序会给出同一磁盘的准确物理磁盘大小。

解决方案非常简单,是对现有问题的扩展

在这里发布我的解决方案,因为完整的代码可能会在将来帮助某人:
(仅供参考:从中获取P/Invoke定义并进行最小修改)


你看到这个问题了吗?也许是IO控制信息?IOCTL\u磁盘\u获取长度\u信息/IOCTL\u磁盘\u获取驱动器_GEOMETRY@LasseV.Karlsen,我在之前和之后发现了这个问题。经过进一步的努力,我发现我没有在.NET框架中正确使用IOCTL\u DISK\u GET\u LENGTH\u INFO(指针和结构的封送使用不正确)。我会相应地更新问题的答案。
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr CreateFile(
    [MarshalAs(UnmanagedType.LPTStr)] string filename,
    [MarshalAs(UnmanagedType.U4)] FileAccess access,
    [MarshalAs(UnmanagedType.U4)] FileShare share,
    IntPtr securityAttributes, // optional SECURITY_ATTRIBUTES struct or IntPtr.Zero
    [MarshalAs(UnmanagedType.U4)] FileMode creationDisposition,
    [MarshalAs(UnmanagedType.U4)] FileAttributes flagsAndAttributes,
    IntPtr templateFile);

[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern bool DeviceIoControl(IntPtr hDevice, uint dwIoControlCode,
    IntPtr lpInBuffer, uint nInBufferSize,
    IntPtr lpOutBuffer, uint nOutBufferSize,
    out uint lpBytesReturned, IntPtr lpOverlapped);

[DllImport("kernel32.dll", SetLastError = true)]
static extern bool CloseHandle(IntPtr hObject);

struct GET_LENGTH_INFORMATION
{
    public long Length;
};
long GetPhysDiskSize(string physDeviceID)
{
    uint IOCTL_DISK_GET_LENGTH_INFO = 0x0007405C;
    uint dwBytesReturned;

    //Example, physDeviceID == @"\\.\PHYSICALDRIVE1"
    IntPtr hVolume = CreateFile(physDeviceID, FileAccess.ReadWrite,
        FileShare.None, IntPtr.Zero, FileMode.Open, FileAttributes.Normal, IntPtr.Zero);

    GET_LENGTH_INFORMATION outputInfo = new GET_LENGTH_INFORMATION();
    outputInfo.Length = 0;

    IntPtr outBuff = Marshal.AllocHGlobal(Marshal.SizeOf(outputInfo));

    bool devIOPass = DeviceIoControl(hVolume,
                        IOCTL_DISK_GET_LENGTH_INFO,
                        IntPtr.Zero, 0,
                        outBuff, (uint)Marshal.SizeOf(outputInfo),
                        out dwBytesReturned,
                        IntPtr.Zero);

    CloseHandle(hVolume);

    outputInfo = (GET_LENGTH_INFORMATION)Marshal.PtrToStructure(outBuff, typeof(GET_LENGTH_INFORMATION));

    Marshal.FreeHGlobal(hVolume);
    Marshal.FreeHGlobal(outBuff);

    return outputInfo.Length;
}