1. 首页
  2. 编程语言
  3. 其他
  4. 获取硬盘序列号,搞了半天,看来不行了

获取硬盘序列号,搞了半天,看来不行了

上传者: 2018-12-07 21:33:31上传 RAR文件 90.9KB 热度 21次
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 } }
用户评论
码姐姐匿名网友 2018-12-07 21:33:31

没获取到系列号

码姐姐匿名网友 2018-12-07 21:33:31

需要修改,可以借鉴一下

码姐姐匿名网友 2018-12-07 21:33:31

这块不太熟,慢慢学着