获取硬盘序列号,搞了半天,看来不行了
using System; using System.Drawing; using System.IO; using System.Runtime.InteropServices; using System.Security; using System.Text; //using Sanxing.Share.Properties; //Download by http://www.codefans.net namespace YPH { ///
/// 执行需要调用 Win32 API 的操作辅助类。 ///
[SuppressUnmanagedCodeSecurity()] public static partial class Win32 { #region 方法 ///
/// 执行获取当前运行的操作系统版本。 ///
///
的值之一,他表示当前运行的操作系 统版本。 private static Platform GetCurrentPlatform() { OperatingSystem os = Environment.OSVersion; Platform pt; switch (os.Platform) { case (PlatformID.Win32Windows): // Win95, Win98 or Me switch (os.Version.Minor) { case (0): // 95 pt = Platform.Windows95; break; case (10): // 98 if (os.Version.Revision.ToString() == "2222A") pt = Platform.Windows982ndEdition; else pt = Platform.Windows98; break; case (90): // winme pt = Platform.WindowsME; break; default: // Unknown pt = Platform.UnKnown; break; } break; case (PlatformID.Win32NT): //Win2k or Xp or 2003 switch (os.Version.Major) { case (3): pt = Platform.WindowsNT351; break; case (4): pt = Platform.WindowsNT40; break; case (5): if (os.Version.Minor == 0) pt = Platform.Windows2000; else if (os.Version.Minor == 1) pt = Platform.WindowsXP; else if (os.Version.Minor == 2) pt = Platform.Windows2003; else pt = Platform.UnKnown; break; default: pt = Platform.UnKnown; break; } break; case (PlatformID.WinCE): // WinCE pt = Platform.WindowsCE; break; case (PlatformID.Win32S): case (PlatformID.Unix): default: pt = Platform.UnKnown; break; } return pt; } ///
/// 表示操作系统平台。 ///
private enum Platform : byte { ///
/// Windows 95 操作系统. ///
Windows95, ///
/// Windows 98 操作系统. ///
Windows98, ///
/// Windows 98 第二版操作系统. ///
Windows982ndEdition, ///
/// Windows ME 操作系统. ///
WindowsME, ///
/// Windows NT 3.51 操作系统. ///
WindowsNT351, ///
/// Windows NT 4.0 操作系统. ///
WindowsNT40, ///
/// Windows 2000 操作系统. ///
Windows2000, ///
/// Windows XP 操作系统. ///
WindowsXP, ///
/// Windows 2003 操作系统. ///
Windows2003, ///
/// Windows CE 操作系统. ///
WindowsCE, ///
/// 操作系统版本未知。 ///
UnKnown } ///
/// 表示IDE设备错误状态代码的常量与数值的对应。 ///
///
其数值与常量定义在 WinIoCtl.h 文件中。
private enum DriverError : byte { ///
/// 设备无错误。 ///
SMART_NO_ERROR = 0, // No error ///
/// 设备IDE控制器错误。 ///
SMART_IDE_ERROR = 1, // Error from IDE controller ///
/// 无效的命令标记。 ///
SMART_INVALID_FLAG = 2, // Invalid command flag ///
/// 无效的命令数据。 ///
SMART_INVALID_COMMAND = 3, // Invalid command byte ///
/// 缓冲区无效(如缓冲区为空或地址错误)。 ///
SMART_INVALID_BUFFER = 4, // Bad buffer (null, invalid addr..) ///
/// 设备编号错误。 ///
SMART_INVALID_DRIVE = 5, // Drive number not valid ///
/// IOCTL错误。 ///
SMART_INVALID_IOCTL = 6, // Invalid IOCTL ///
/// 无法锁定用户的缓冲区。 ///
SMART_ERROR_NO_MEM = 7, // Could not lock user's buffer ///
/// 无效的IDE注册命令。 ///
SMART_INVALID_REGISTER = 8, // Some IDE Register not valid ///
/// 无效的命令设置。 ///
SMART_NOT_SUPPORTED = 9, // Invalid cmd flag set ///
/// 指定要查找的设别索引号无效。 ///
SMART_NO_IDE_DEVICE = 10 } public static void ChangeByteOrder(byte[] charArray) { byte temp; for (int i = 0; i < charArray.Length; i += 2) { temp = charArray[i]; charArray[i] = charArray[i + 1]; charArray[i + 1] = temp; } } ///
/// 根据指定的设备信息生成设备的详细信息。 ///
///
一个
///
private static HDiskInfo GetHardDiskInfo(IdSector phdinfo) { HDiskInfo hdd = new HDiskInfo(); hdd.ModuleNumber = Encoding.ASCII.GetString(phdinfo.sModelNumber).Trim(); hdd.Firmware = Encoding.ASCII.GetString(phdinfo.sFirmwareRev).Trim(); hdd.SerialNumber = Encoding.ASCII.GetString(phdinfo.sSerialNumber).Trim(); hdd.Capacity = phdinfo.ulTotalAddressableSectors / 2 / 1024; hdd.BufferSize = phdinfo.wBufferSize / 1024; return hdd; } ///
/// 获取在NT平台下指定序列号的硬盘信息。 ///
///
物理磁盘的数量。 ///
public static HDiskInfo GetHddInfoNT(byte driveIndex) { GetVersionOutParams vers = new GetVersionOutParams(); SendCmdInParams inParam = new SendCmdInParams(); SendCmdOutParams outParam = new SendCmdOutParams(); uint bytesReturned = 0; // 使用 Win2000 或 Xp下的方法获取硬件信息 // 获取设备的句柄。 IntPtr hDevice = CreateFile(string.Format(@"\\.\PhysicalDrive{0}", driveIndex), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero); // 开始检查 if (hDevice == IntPtr.Zero) throw new UnauthorizedAccessException("执行 Win32 API 函数 CreateFile 失败。"); if (0 == DeviceIoControl(hDevice, SMART_GET_VERSION, IntPtr.Zero, 0, ref vers, (uint)Marshal.SizeOf(vers), ref bytesReturned, IntPtr.Zero)) { CloseHandle(hDevice); //throw new IOException(string.Format(Resources.Win32_DeviceIoControlErr, "SMART_GET_VERSION")); } // 检测IDE控制命令是否支持 if (0 == (vers.fCapabilities & 1)) { CloseHandle(hDevice); //throw new IOException(Resources.Win32_DeviceIoControlNotSupport); } // Identify the IDE drives if (0 != (driveIndex & 1)) inParam.irDriveRegs.bDriveHeadReg = 0xb0; else inParam.irDriveRegs.bDriveHeadReg = 0xa0; if (0 != (vers.fCapabilities & (16 >> driveIndex))) { // We don't detect a ATAPI device. CloseHandle(hDevice); //throw new IOException(Resources.Win32_DeviceIoControlNotSupport); } else inParam.irDriveRegs.bCommandReg = 0xec; inParam.bDriveNumber = driveIndex; inParam.irDriveRegs.bSectorCountReg = 1; inParam.irDriveRegs.bSectorNumberReg = 1; inParam.cBufferSize = 512; if (0 == DeviceIoControl( hDevice, SMART_RCV_DRIVE_DATA, ref inParam, (uint)Marshal.SizeOf(inParam), ref outParam, (uint)Marshal.SizeOf(outParam), ref bytesReturned, IntPtr.Zero)) { CloseHandle(hDevice); //throw new IOException( // string.Format(Resources.Win32_DeviceIoControlErr, "SMART_RCV_DRIVE_DATA")); } CloseHandle(hDevice); ChangeByteOrder(outParam.bBuffer.sModelNumber); ChangeByteOrder(outParam.bBuffer.sSerialNumber); ChangeByteOrder(outParam.bBuffer.sFirmwareRev); return GetHardDiskInfo(outParam.bBuffer); } #endregion #region Win32 ///
/// 取得指定窗口的系统菜单的句柄。 ///
///
指向要获取系统菜单窗口的
句柄。 ///
获取系统菜单的方式。设置为 true,表示接收原始的系统菜单,否则设置为 false 。 ///
指向要获取的系统菜单的
句柄。
[DllImport("user32.dll", SetLastError = true)] private static extern IntPtr GetSystemMenu(IntPtr hwnd, bool bRevert); ///
/// 获取指定的菜单中条目(菜单项)的数量。 ///
///
指向要获取菜单项数量的系统菜单的
句柄。 ///
菜单中的条目数量
[DllImport("user32.dll", SetLastError = true)] private static extern int GetMenuItemCount(IntPtr hMenu); ///
/// 删除指定的菜单条目。 ///
///
指向要移除的菜单的
。 ///
欲改变的菜单条目的标识符。 ///
///
非零表示成功,零表示失败。
///
/// 如果在
中使用了
,则在
参数表示菜单项的索引; /// 如果在
中使用了 MF_BYCOMMAND,则在
中使用菜单项的ID。 ///
[DllImport("user32.dll", SetLastError = true)] private static extern int RemoveMenu(IntPtr hMenu, int uPosition, int uFlags); ///
/// 关闭一个指定的指针对象指向的设备。。 ///
///
要关闭的句柄
对象。 ///
成功返回 0 ,不成功返回非零值。
[DllImport("kernel32.dll", SetLastError = true)] private static extern int CloseHandle(IntPtr hObject); ///
/// 执行打开/建立资源的功能。 ///
///
指定要打开的设备或文件的名称。 ///
///
Win32 常量,用于控制对设备的读访问、写访问或读/写访问的常数。内容如下表: ///
///
///
名称
///
说明
///
///
///
GENERIC_READ
指定对设备进行读取访问。
///
///
///
GENERIC_WRITE
指定对设备进行写访问。
///
///
0
如果值为零,则表示只允许获取与一个设备有关的信息。
///
///
/// ///
指定打开设备时的文件共享模式 ///
///
Win32 常量,指定操作系统打开文件的方式。内容如下表: ///
///
///
名称
说明
///
///
CREATE_NEW
///
指定操作系统应创建新文件。如果文件存在,则抛出
异常。
///
///
CREATE_ALWAYS
指定操作系统应创建新文件。如果文件已存在,它将被改写。
///
///
/// ///
///
///
使用函数打开的设备的句柄。
///
/// 本函数可以执行打开或建立文件、文件流、目录/文件夹、物理磁盘、卷、系统控制的缓冲区、磁带设备、 /// 通信资源、邮件系统和命名管道。 ///
[DllImport("kernel32.dll", SetLastError = true)] private static extern IntPtr CreateFile(string lpFileName, uint dwDesiredAccess, uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile); ///
/// 对设备执行指定的操作。 ///
///
要执行操作的设备句柄。 ///
Win32 API 常数,输入的是以 FSCTL_ 为前缀的常数,定义在 /// WinIoCtl.h 文件内,执行此重载方法必须输入 SMART_GET_VERSION 。 ///
当参数为指针时,默认的输入值是 0 。 ///
输入缓冲区的字节数量。 ///
一个 GetVersionOutParams ,表示执行函数后输出的设备检查。 ///
输出缓冲区的字节数量。 ///
实际装载到输出缓冲区的字节数量。 ///
同步操作控制,一般不使用,默认值为 0 。 ///
非零表示成功,零表示失败。
[DllImport("kernel32.dll", SetLastError = true)] private static extern int DeviceIoControl(IntPtr hDevice, uint dwIoControlCode, IntPtr lpInBuffer, uint nInBufferSize, ref GetVersionOutParams lpOutBuffer, uint nOutBufferSize, ref uint lpBytesReturned, [Out] IntPtr lpOverlapped); ///
/// 对设备执行指定的操作。 ///
///
要执行操作的设备句柄。 ///
Win32 API 常数,输入的是以 FSCTL_ 为前缀的常数,定义在 /// WinIoCtl.h 文件内,执行此重载方法必须输入 SMART_SEND_DRIVE_COMMAND 或 SMART_RCV_DRIVE_DATA 。 ///
一个 SendCmdInParams 结构,它保存向系统发送的查询要求具体命令的数据结构。 ///
输入缓冲区的字节数量。 ///
一个 SendCmdOutParams 结构,它保存系统根据命令返回的设备相信信息二进制数据。 ///
输出缓冲区的字节数量。 ///
实际装载到输出缓冲区的字节数量。 ///
同步操作控制,一般不使用,默认值为 0 。 ///
非零表示成功,零表示失败。
[DllImport("kernel32.dll", SetLastError = true)] private static extern int DeviceIoControl(IntPtr hDevice, uint dwIoControlCode, ref SendCmdInParams lpInBuffer, uint nInBufferSize, ref SendCmdOutParams lpOutBuffer, uint nOutBufferSize, ref uint lpBytesReturned, [Out] IntPtr lpOverlapped); #endregion #region 结构 ///
/// 保存当前计算机 IDE 设备(硬盘)的硬件信息的结构。 ///
[Serializable] public struct HDiskInfo { ///
/// 硬盘型号。 ///
public string ModuleNumber; ///
/// 硬盘的固件版本。 ///
public string Firmware; ///
/// 硬盘序列号。 ///
public string SerialNumber; ///
/// 硬盘容量,以M为单位。 ///
public uint Capacity; ///
/// 设备缓存大小(以M为单位)。 ///
public int BufferSize; } ///
/// 表示使用 DeviceIoControl 函数时保存返回的驱动器硬件信息的结构 ///
///
>此数据结构定义在 WinIoCtl.h 文件名为 _GETVERSIONINPARAMS 结构中。
[StructLayout(LayoutKind.Sequential, Pack = 1)] private struct GetVersionOutParams { ///
/// IDE设备的二进制硬件版本。 ///
public byte bVersion; ///
/// IDE设备的二进制修订版本。 ///
public byte bRevision; ///
/// 此值操作系统没有使用,使用此数据结构时被设置为 0 。 ///
public byte bReserved; ///
/// IDE设备的二进制映射。 ///
public byte bIDEDeviceMap; ///
/// IDE设备的二进制容量数据。 ///
public uint fCapabilities; ///
/// 保留内容,不使用。 ///
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public uint[] dwReserved; // For future use. } ///
/// 一个数据结构,表示使用 DeviceIoControl 函数时发送到操作系统中的命令数据结构 SendCmdInParams 的成员结构。 /// 它表示要获取磁盘设备性能参数的具体定义规则。 ///
///
///
此数据结构定义在 WinIoCtl.h 文件名为 _IDEREGS 中。
[StructLayout(LayoutKind.Sequential, Pack = 1)] private struct IdeRegs { ///
/// 发送到操作系统的注册命令,此为系统的 SMART Command 。 ///
public byte bFeaturesReg; ///
/// 获取IDE设备扇区数。 ///
public byte bSectorCountReg; ///
/// 获取IDE设备编号。 ///
public byte bSectorNumberReg; ///
/// 获取IDE设备低端柱面值。 ///
public byte bCylLowReg; ///
/// 获取IDE设备高端柱面值。 ///
public byte bCylHighReg; ///
/// 获取IDE设备的头信息。 ///
public byte bDriveHeadReg; ///
/// 获取IDE设备的真正命令。 ///
public byte bCommandReg; ///
/// 保留内容,此值应设置为 0 。 ///
public byte bReserved; } ///
/// 保存执行 DeviceIoControl 函数时向系统提交的执行操作命令。 ///
///
///
此数据结构定义在 WinIoCtl.h 文件名为 _SENDCMDINPARAMS 中。
[StructLayout(LayoutKind.Sequential, Pack = 1)] private 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; ///
/// 保存当前 SendCmdInParams 结构填充数据后的大小。 ///
public byte bBuffer; } ///
/// 当执行 DeviceIoControl 函数后系统返回的 SendCmdOutParams 结构中 /// 保存磁盘设备当前错误信息的数据结构。 ///
///
///
/// 此数据结构定义在 WinIoCtl.h 文件名为 _DRIVERSTATUS 中。 ///
/// 错误代码如下表:
///
///
///
名称
///
说明
///
SMART_NO_ERROR = 0
///
没有错误。
///
SMART_IDE_ERROR = 1
///
IDE控制器错误
。
///
SMART_INVALID_FLAG = 2
///
发送的命令标记无效。
///
SMART_INVALID_COMMAND = 3
///
发送的二进制命令无效。
///
SMART_INVALID_BUFFER = 4
///
二进制缓存无效(缓存为空或者无效地址)。
///
SMART_INVALID_DRIVE = 5
///
物理驱动器编号无效。
///
SMART_INVALID_IOCTL = 6
///
无效的IOCTL。
///
SMART_ERROR_NO_MEM = 7
///
使用的缓冲区无法锁定。
///
SMART_INVALID_REGISTER = 8
///
IDE注册命令无效。
///
SMART_NOT_SUPPORTED = 9
///
命令标记设置无效。
///
SMART_NO_IDE_DEVICE = 10
///
发送的物理驱动器索引超过限制。
///
///
///
[StructLayout(LayoutKind.Sequential, Pack = 1)] private struct DriverStatus { ///
/// 如果检查的IDE设备发生错误,保存的错误代码,0 表示没有错误。 ///
public byte bDriverError; ///
/// IDE设备被注册的错误内容。 ///
public byte bIDEStatus; ///
/// 保留的数据,不使用。 ///
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public byte[] bReserved; ///
/// 保留的数据,不使用。 ///
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public uint[] dwReserved; } ///
/// 表示当执行 DeviceIoControl 函数后保存系统根据查询命令返回的磁盘设备信息的数据结构。 ///
[StructLayout(LayoutKind.Sequential, Pack = 1)] private struct SendCmdOutParams { ///
/// 表示所有二进制信息的缓存大小。 ///
public uint cBufferSize; ///
/// 表示查询到设备的错误信息状态。 ///
public DriverStatus DriverStatus; ///
/// 表示系统返回的设备硬件信息的二进制数据结构。 ///
public IdSector bBuffer; } ///
/// 当执行 DeviceIoControl 函数后系统返回的 SendCmdOutParams 结构中 /// 保存磁盘设备的硬件信息的数据结构。 ///
///
[StructLayout(LayoutKind.Sequential, Pack = 1, Size = 512)] private 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; ///
/// 设备缓存容量(单位是byte)。 ///
public ushort wBufferSize; ///
/// 设备的错误检查和纠正(ECC)数据的大小。 ///
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; ///
/// 设备的容量大小(单位Byte)。 ///
public ushort wCapabilities; ///
/// 第一个保留的内容,不使用。 ///
public ushort wReserved1; ///
/// 设备的PIO模式巡道时间。 ///
public ushort wPIOTiming; ///
/// 设备DMA 模式巡道时间。 ///
public ushort wDMATiming; ///
/// 设备的总线类型,如SCSI,IDE等。 ///
public ushort wBS; ///
/// 设备的当前柱面数量。 ///
public ushort wNumCurrentCyls; ///
/// 设备当前磁头数量。 ///
public ushort wNumCurrentHeads; ///
/// 设备的当前扇区的磁道数量。 ///
public ushort wNumCurrentSectorsPerTrack; ///
/// 设备的当前扇区容量(单位byte)。 ///
public uint ulCurrentSectorCapacity; ///
/// 多扇区读写模式支持。 ///
public ushort wMultSectorStuff; ///
/// 用户是否可自定义扇区地址(LBA模式)支持。 ///
public uint ulTotalAddressableSectors; ///
/// 单指令DMA模式。 ///
public ushort wSingleWordDMA; ///
/// 多指令DMA模式。 ///
public ushort wMultiWordDMA; ///
/// 保留内容,不使用。 ///
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)] public byte[] bReserved; } ///
/// ///
[StructLayout(LayoutKind.Sequential)] public struct RECT { ///
/// ///
///
///
///
///
public RECT(int left, int top, int right, int bottom) { this.left = left; this.top = top; this.right = right; this.bottom = bottom; } ///
/// ///
///
public RECT(Rectangle r) { left = r.Left; top = r.Top; right = r.Right; bottom = r.Bottom; } ///
/// ///
public int left; ///
/// ///
public int top; ///
/// ///
public int right; ///
/// ///
public int bottom; ///
/// ///
///
///
///
///
///
public static RECT FromXYWH(int x, int y, int width, int height) { return new RECT(x, y, x + width, y + height); } ///
/// ///
public Size Size { get { return new Size(right - left, bottom - top); } } } ///
/// ///
[StructLayout(LayoutKind.Sequential)] public sealed class SCROLLINFO { public SCROLLINFO() { this.cbSize = Marshal.SizeOf(typeof(SCROLLINFO)); } public SCROLLINFO(int mask, int min, int max, int page, int pos) { this.cbSize = Marshal.SizeOf(typeof(SCROLLINFO)); this.fMask = mask; this.nMin = min; this.nMax = max; this.nPage = page; this.nPos = pos; } public int cbSize; public int fMask; public int nMin; public int nMax; public int nPage; public int nPos; public int nTrackPos; } #endregion #region 常量 ///
/// Win32 API 常数,指示在使用
函数时指定使用索引数而不是使用ID。 ///
private const int MF_BYPOSITION = 0x00000400; private const uint FILE_SHARE_READ = 0x00000001; private const uint FILE_SHARE_WRITE = 0x00000002; private const uint FILE_SHARE_DELETE = 0x00000004; private const uint SMART_GET_VERSION = 0x00074080; // SMART_GET_VERSION private const uint SMART_SEND_DRIVE_COMMAND = 0x0007c084; // SMART_SEND_DRIVE_COMMAND private const uint SMART_RCV_DRIVE_DATA = 0x0007c088; // SMART_RCV_DRIVE_DATA private const uint GENERIC_READ = 0x80000000; private const uint GENERIC_WRITE = 0x40000000; private const uint CREATE_NEW = 1; private const uint OPEN_EXISTING = 3; private const uint BUFFER_SIZE = 512; private static readonly Platform currentOs; #endregion } }
用户评论
没获取到系列号
需要修改,可以借鉴一下
这块不太熟,慢慢学着