如何得到硬盤序列號(hào)[C#]

字號(hào):

硬盤序列號(hào)(Serial Number)不等于卷標(biāo)號(hào)(Volume Name),后者雖然很容易得到,但是格式化分區(qū)后就會(huì)重寫,不可靠。遺憾的是很多朋友往往分不清這一點(diǎn)。
    要得到硬盤的物理序列號(hào),可以通過WMI,也就是Win32_PhysicalMedia.SerialNumber。可惜的是Windows 98/ME的WMI并不支持這個(gè)類,訪問時(shí)會(huì)出現(xiàn)異常。
    受陸麟的例子的啟發(fā),我們還可以通過S.M.A.R.T.接口,直接從RING3調(diào)用API DeviceIoControl()來獲取硬盤信息,而不需要寫VXD或者DRIVER。這樣這個(gè)問題就解決了,我對(duì)它進(jìn)行了封裝,大量使用了P/Invoke技術(shù),一個(gè)完整的Library。支持Windows 98-2003。
    使用上很簡(jiǎn)單:
    HardDiskInfo hdd = AtapiDevice.GetHddInfo(0); // 第一個(gè)硬盤
    Console.WriteLine("Module Number: {0}", hdd.ModuleNumber);
    Console.WriteLine("Serial Number: {0}", hdd.SerialNumber);
    Console.WriteLine("Firmware: {0}", hdd.Firmware);
    Console.WriteLine("Capacity: {0} M", hdd.Capacity);
    下面是全部代碼:
    using System;
    using System.Runtime.InteropServices;
    using System.Text;
    namespace Sunmast.Hardware
    {
    [Serializable]
    public struct HardDiskInfo
    {
    ///
    /// 型號(hào)
    ///

    public string ModuleNumber;
    ///
    /// 固件版本
    ///

    public string Firmware;
    ///
    /// 序列號(hào)
    ///

    public string SerialNumber;
    ///
    /// 容量,以M為單位
    ///

    public uint Capacity;
    }
    #region Internal Structs
    [StructLayout(LayoutKind.Sequential, Pack=1)]
    internal struct GetVersionOutParams
    {
    public byte bVersion;
    public byte bRevision;
    public byte bReserved;
    public byte bIDEDeviceMap;
    public uint fCapabilities;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst=4)]
    public uint[] dwReserved; // For future use.
    }
    [StructLayout(LayoutKind.Sequential, Pack=1)]
    internal struct IdeRegs
    {
    public byte bFeaturesReg;
    public byte bSectorCountReg;
    public byte bSectorNumberReg;
    public byte bCylLowReg;
    public byte bCylHighReg;
    public byte bDriveHeadReg;
    public byte bCommandReg;
    public byte bReserved;
    }
    [StructLayout(LayoutKind.Sequential, Pack=1)]
    internal struct SendCmdInParams
    {
    public uint cBufferSize;
    public IdeRegs irDriveRegs;
    public byte bDriveNumber;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst=3)]
    public byte[] bReserved;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst=4)]
    public uint[] dwReserved;
    public byte bBuffer;
    }
    [StructLayout(LayoutKind.Sequential, Pack=1)]
    internal struct DriverStatus
    {
    public byte bDriverError;
    public byte bIDEStatus;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst=2)]
    public byte[] bReserved;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst=2)]
    public uint[] dwReserved;
    }
    [StructLayout(LayoutKind.Sequential, Pack=1)]
    internal struct SendCmdOutParams
    {
    public uint cBufferSize;
    public DriverStatus DriverStatus;
    public IdSector bBuffer;
    }
    [StructLayout(LayoutKind.Sequential, Pack=1, Size=512)]
    internal struct IdSector
    {
    public ushort wGenConfig;
    public ushort wNumCyls;
    public ushort wReserved;
    public ushort wNumHeads;
    public ushort wBytesPerTrack;
    public ushort wBytesPerSector;
    public ushort wSectorsPerTrack;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst=3)]
    public ushort[] wVendorUnique;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst=20)]
    public byte[] sSerialNumber;
    public ushort wBufferType;
    public ushort wBufferSize;
    public ushort wECCSize;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst=8)]
    public byte[] sFirmwareRev;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst=40)]
    public byte[] sModelNumber;
    public ushort wMoreVendorUnique;
    public ushort wDoubleWordIO;
    public ushort wCapabilities;
    public ushort wReserved1;
    public ushort wPIOTiming;
    public ushort wDMATiming;
    public ushort wBS;
    public ushort wNumCurrentCyls;
    public ushort wNumCurrentHeads;
    public ushort wNumCurrentSectorsPerTrack;
    public uint ulCurrentSectorCapacity;
    public ushort wMultSectorStuff;
    public uint ulTotalAddressableSectors;
    public ushort wSingleWordDMA;
    public ushort wMultiWordDMA;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst=128)]
    public byte[] bReserved;
    }
    #endregion
    ///
    /// ATAPI驅(qū)動(dòng)器相關(guān)
    ///

    public class AtapiDevice
    {