1、NET获取硬盘序列号的几个方法最近作软件注册,收集了很多.NET相关的获取硬盘物理序列号的方法,主要分为使用WMI方式和API方式。但这些方法均可能有问题。1,使用WMI方式,有的机器根本取不到硬盘序列号,有的方式在Vista下面会报错。常用的使用WMI的方式主要有下面一些方式:class HardDrive private string model = null; private string type = null; private string serialNo = null; public string Model get return model; set model = value
2、; public string Type get return type; set type = value; public string SerialNo get return serialNo; set serialNo = value; class TestProgram / / The main entry point for the application. / STAThread static void Main(string args) /在Vista下面失败 ArrayList hdCollection = new ArrayList(); ManagementObjectSe
3、archer searcher = new ManagementObjectSearcher(SELECT * FROM Win32_DiskDrive); foreach(ManagementObject wmi_HD in searcher.Get() HardDrive hd = new HardDrive(); hd.Model = wmi_HDModel.ToString(); hd.Type = wmi_HDInterfaceType.ToString(); hdCollection.Add(hd); searcher = new ManagementObjectSearcher(
4、SELECT * FROM Win32_PhysicalMedia); int i = 0; foreach(ManagementObject wmi_HD in searcher.Get() / get the hard drive from collection / using index HardDrive hd = (HardDrive)hdCollectioni; / get the hardware serial no. if (wmi_HDSerialNumber = null) hd.SerialNo = None; else hd.SerialNo = wmi_HDSeria
5、lNumber.ToString(); +i; / Display available hard drives foreach(HardDrive hd in hdCollection) Console.WriteLine(Modeltt: + hd.Model); Console.WriteLine(Typett: + hd.Type); Console.WriteLine(Serial No.t: + hd.SerialNo); Console.WriteLine(); / Pause application Console.WriteLine(Press Enter to exit.);
6、 Console.ReadLine(); 上面的方式先查询Win32_DiskDrive,然后再查询 Win32_PhysicalMedia,经过测试,这种方式不能保证在所有机器上均取得硬盘序列号,而且在Vista下面还会出错,程序直接抛出无法处理的异常。另外,还可以使用另外一WMI方式,就是查询 PNPDeviceID 的 signature,代码如下:/ / 获取硬盘唯一序列号(不是卷标号),可能需要以管理员身份运行程序 / / public static string GetHdId() ManagementObjectSearcher wmiSearcher = new Managem
7、entObjectSearcher(); /* * PNPDeviceID 的数据是由四部分组成的: 1、接口,通常有 IDE,ATA,SCSI; 2、型号 3、(可能)驱动版本号 4、(可能)硬盘的出厂序列号 * * */ /signature 需要程序以管理员身份运行(经过测试,2003系统上非管理员身份也可以运行,查相关资料说,可能在2000系统上获取的值为空) wmiSearcher.Query = new SelectQuery( Win32_DiskDrive, , new string PNPDeviceID, signature ); ManagementObjectColle
8、ction myCollection = wmiSearcher.Get(); ManagementObjectCollection.ManagementObjectEnumerator em = myCollection.GetEnumerator(); em.MoveNext(); ManagementBaseObject mo = em.Current; /string id = mo.PropertiesPNPDeviceID.Value.ToString().Trim(); string id = mo.Propertiessignature.Value.ToString().Tri
9、m(); return id; 有人说,使用 signature 需要程序以管理员身份运行(经过测试,2003系统上非管理员身份也可以运行),而且查询相关资料说,可能在2000系统上获取的值为空。使用这种方式,在Vista上面工作良好。经过测试,使用 signature 均能够取得硬盘序列号,但是跟 Win32_PhysicalMedia 查询出来的号不一样。目前我也不能肯定 使用 signature 能够100%取道硬盘序列号。 使用WMI方式需要客户机开启WMI服务,但这个往往不能保证,所以使用这种方式有一定局限性。 2,使用API方式。在网上找到一片资料,说使用 RING3调用 API
10、DeviceIoControl()来获取硬盘信息,下面是原话:硬盘序列号(Serial Number)不等于卷标号(Volume Name),后者虽然很容易得到,但是格式化分区后就会重写,不可靠。遗憾的是很多朋友往往分不清这一点。要得到硬盘的物理序列号,可以通过WMI,也就是Win32_PhysicalMedia.SerialNumber。可惜的是Windows 98/ME的WMI并不支持这个类,访问时会出现异常。受陆麟的例子的启发,我们还可以通过S.M.A.R.T.接口,直接从RING3调用 API DeviceIoControl()来获取硬盘信息,而不需要写VXD或者DRIVER。这样这个
11、问题就解决了,我对它进行了封装,大量使用了 P/Invoke技术,一个完整的Library。支持Windows 98-2003。使用上很简单:HardDiskInfo hdd = AtapiDevice.GetHddInfo(0); / 第一个硬盘Console.WriteLine(Module Number: 0, hdd.ModuleNumber);Console.WriteLine(Serial Number: 0, hdd.SerialNumber);Console.WriteLine(Firmware: 0, hdd.Firmware);Console.WriteLine(Capac
12、ity: 0 M, hdd.Capacity); 感谢原文作者的贡献,(在这里我已经不知道原文作者是谁了,网上的文章都是转载的),经过测试,这种方式比较准确,但是需要管理员权限运行。下面把代码分享:using System; using System.Runtime.InteropServices; using System.Text; namespace HardwareUtility Serializable public struct HardDiskInfo / / 型号 / public string ModuleNumber; / / 固件版本 / public string Fi
13、rmware; / / 序列号 / 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 fCa
14、pabilities; 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 bCyl
15、HighReg; 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 b
16、yte 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 b
17、Reserved; 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 =
18、 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 wVendorUniq
19、ue; 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 byt
20、e 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 wNumCurrentSectorsP
21、erTrack; 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驱动器相关 / public class AtapiDe
22、vice #region DllImport DllImport(kernel32.dll, SetLastError = true) static extern int CloseHandle(IntPtr hObject); DllImport(kernel32.dll, SetLastError = true) static extern IntPtr CreateFile( string lpFileName, uint dwDesiredAccess, uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisp
23、osition, uint dwFlagsAndAttributes, IntPtr hTemplateFile); DllImport(kernel32.dll) static extern int DeviceIoControl( IntPtr hDevice, uint dwIoControlCode, IntPtr lpInBuffer, uint nInBufferSize, ref GetVersionOutParams lpOutBuffer, uint nOutBufferSize, ref uint lpBytesReturned, Out IntPtr lpOverlapp
24、ed); DllImport(kernel32.dll) static extern int DeviceIoControl( IntPtr hDevice, uint dwIoControlCode, ref SendCmdInParams lpInBuffer, uint nInBufferSize, ref SendCmdOutParams lpOutBuffer, uint nOutBufferSize, ref uint lpBytesReturned, Out IntPtr lpOverlapped); const uint DFP_GET_VERSION = 0x00074080
25、; const uint DFP_SEND_DRIVE_COMMAND = 0x0007c084; const uint DFP_RECEIVE_DRIVE_DATA = 0x0007c088; const uint GENERIC_READ = 0x80000000; const uint GENERIC_WRITE = 0x40000000; const uint FILE_SHARE_READ = 0x00000001; const uint FILE_SHARE_WRITE = 0x00000002; const uint CREATE_NEW = 1; const uint OPEN
26、_EXISTING = 3; #endregion #region GetHddInfo / / 获得硬盘信息 / / 硬盘序号 / 硬盘信息 / / 参考lu0的文章:http:/lu0s1.3322.org/App/2k1103.html / by sunmast for everyone / thanks lu0 for his great works / 在Windows 98/ME中,S.M.A.R.T并不缺省安装,请将SMARTVSD.VXD拷贝到%SYSTEM%IOSUBSYS目录下。 / 在Windows 2000/2003下,需要Administrators组的权限。 / /
27、 / AtapiDevice.GetHddInfo() / public static HardDiskInfo GetHddInfo(byte driveIndex) switch (Environment.OSVersion.Platform) case PlatformID.Win32Windows: return GetHddInfo9x(driveIndex); case PlatformID.Win32NT: return GetHddInfoNT(driveIndex); case PlatformID.Win32S: throw new NotSupportedExceptio
28、n(Win32s is not supported.); case PlatformID.WinCE: throw new NotSupportedException(WinCE is not supported.); default: throw new NotSupportedException(Unknown Platform.); #region GetHddInfo9x private static HardDiskInfo GetHddInfo9x(byte driveIndex) GetVersionOutParams vers = new GetVersionOutParams(); SendCmdInP
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1