using ET; using System; using System.Collections; using System.Collections.Generic; using System.Management; using System.Runtime.InteropServices; using System.Security.Cryptography; using System.Text; using UnityEngine; using System.Management.Instrumentation; using System.Net.NetworkInformation; public class DiskID { private const string KERNEL = "kernel32.dll"; public enum DriveCommand : uint { GetVersion = 0x00074080, SendDriveCommand = 0x0007c084, ReceiveDriveData = 0x0007c088 } [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct DriverStatus { public byte DriverError; public byte IDEError; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)] public byte[] Reserved; } [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct DriveIdentifyResult { public uint BufferSize; public DriverStatus DriverStatus; public Identify Identify; } [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct Identify { public ushort GeneralConfiguration; public ushort NumberOfCylinders; public ushort Reserved; public ushort NumberOfHeads; public ushort UnformattedBytesPerTrack; public ushort UnformattedBytesPerSector; public ushort SectorsPerTrack; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public ushort[] VendorUnique; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] public byte[] SerialNumber; public ushort BufferType; public ushort BufferSectorSize; public ushort NumberOfEccBytes; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] FirmwareRevision; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 40)] public byte[] ModelNumber; public ushort MoreVendorUnique; public ushort DoubleWordIo; public ushort Capabilities; public ushort MoreReserved; public ushort PioCycleTimingMode; public ushort DmaCycleTimingMode; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 406)] public byte[] More; } [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct DriveCommandParameter { public uint BufferSize; public CommandBlockRegisters Registers; public byte DriveNumber; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] public byte[] Reserved; } [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct CommandBlockRegisters { public RegisterFeature Features; public byte SectorCount; public byte LBALow; public byte LBAMid; public byte LBAHigh; public byte Device; public RegisterCommand Command; public byte Reserved; } public enum RegisterFeature : byte { /// /// Read SMART data. /// SmartReadData = 0xD0, /// /// Read SMART thresholds. /// SmartReadThresholds = 0xD1, /* obsolete */ /// /// Autosave SMART data. /// SmartAutosave = 0xD2, /// /// Save SMART attributes. /// SmartSaveAttr = 0xD3, /// /// Set SMART to offline immediately. /// SmartImmediateOffline = 0xD4, /// /// Read SMART log. /// SmartReadLog = 0xD5, /// /// Write SMART log. /// SmartWriteLog = 0xD6, /// /// Write SMART thresholds. /// SmartWriteThresholds = 0xD7, /* obsolete */ /// /// Enable SMART. /// SmartEnableOperations = 0xD8, /// /// Disable SMART. /// SmartDisableOperations = 0xD9, /// /// Get SMART status. /// SmartStatus = 0xDA, /// /// Set SMART to offline automatically. /// SmartAutoOffline = 0xDB, /* obsolete */ } public enum RegisterCommand : byte { /// /// SMART data requested. /// SmartCmd = 0xB0, /// /// Identify data is requested. /// IdCmd = 0xEC, } [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)] [return: MarshalAsAttribute(UnmanagedType.Bool)] public static extern bool DeviceIoControl(IntPtr handle, DriveCommand command, ref DriveCommandParameter parameter, int parameterSize, out DriveIdentifyResult result, int resultSize, out uint bytesReturned, IntPtr overlapped); [Flags] public enum AccessMode : uint { Read = 0x80000000, Write = 0x40000000, Execute = 0x20000000, All = 0x10000000 } [Flags] public enum ShareMode : uint { None = 0, Read = 1, Write = 2, Delete = 4 } public enum CreationMode : uint { New = 1, CreateAlways = 2, OpenExisting = 3, OpenAlways = 4, TruncateExisting = 5 } [Flags] public enum FileAttribute : uint { Readonly = 0x00000001, Hidden = 0x00000002, System = 0x00000004, Directory = 0x00000010, Archive = 0x00000020, Device = 0x00000040, Normal = 0x00000080, Temporary = 0x00000100, SparseFile = 0x00000200, ReparsePoint = 0x00000400, Compressed = 0x00000800, Offline = 0x00001000, NotContentIndexed = 0x00002000, Encrypted = 0x00004000, } [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Unicode)] public static extern IntPtr CreateFile(string fileName, AccessMode desiredAccess, ShareMode shareMode, IntPtr securityAttributes, CreationMode creationDisposition, FileAttribute flagsAndAttributes, IntPtr templateFilehandle); private const int MAX_DRIVES = 32; public IntPtr InvalidHandle { get { return (IntPtr)(-1); } } public void Start() { // 取得设备硬盘的物理序列号 for (int driveIndex = 0; driveIndex < MAX_DRIVES; driveIndex++) { IntPtr deviceHandle = OpenDrive(driveIndex); if (deviceHandle == InvalidHandle) break; DriveCommandParameter parameter = new DriveCommandParameter(); DriveIdentifyResult result; uint bytesReturned; parameter.DriveNumber = (byte)driveIndex; parameter.Registers.Command = RegisterCommand.IdCmd; bool valid = DeviceIoControl(deviceHandle, DriveCommand.ReceiveDriveData, ref parameter, Marshal.SizeOf(parameter), out result, Marshal.SizeOf(typeof(DriveIdentifyResult)), out bytesReturned, IntPtr.Zero); if (!valid) { break; } string hddName = GetString(result.Identify.ModelNumber); string firmwareRevision = GetString(result.Identify.FirmwareRevision); Debug.Log("序列号:" + GetString(result.Identify.SerialNumber)); Debug.Log("硬盘编号:" + hddName); Debug.Log("firmwareRevision:" + firmwareRevision); } // 取得设备硬盘的卷标号 此方法为取硬盘逻辑分区序列号,重新格式化会改变 Debug.Log("C盘卷标号:" + GetDiskVolume("C")); } public IntPtr OpenDrive(int driveNumber) { return CreateFile(@"\\.\PhysicalDrive" + driveNumber, AccessMode.Read | AccessMode.Write, ShareMode.Read | ShareMode.Write, IntPtr.Zero, CreationMode.OpenExisting, FileAttribute.Device, IntPtr.Zero); } private string GetString(byte[] bytes) { char[] chars = new char[bytes.Length]; for (int i = 0; i < bytes.Length; i += 2) { chars[i] = (char)bytes[i + 1]; chars[i + 1] = (char)bytes[i]; } return new string(chars).Trim(new char[] { ' ', '\0' }); } #region 获取硬盘序列号 [DllImport("kernel32.dll")] private static extern int GetVolumeInformation( string lpRootPathName, string lpVolumeNameBuffer, int nVolumeNameSize, ref int lpVolumeSerialNumber, int lpMaximumComponentLength, int lpFileSystemFlags, string lpFileSystemNameBuffer, int nFileSystemNameSize ); /// /// 获取硬盘序列号 /// /// 硬盘盘符[c|d|e|....] /// public static string GetDiskVolume(string drvID) { const int MAX_FILENAME_LEN = 256; int retVal = 0; int lpMaximumComponentLength = 0; int lpFileSystemFlags = 0; string lpVolumeNameBuffer = null; string lpFileSystemNameBuffer = null; int i = GetVolumeInformation( drvID + @":\", lpVolumeNameBuffer, MAX_FILENAME_LEN, ref retVal, lpMaximumComponentLength, lpFileSystemFlags, lpFileSystemNameBuffer, MAX_FILENAME_LEN ); return retVal.ToString("x"); } #endregion } public class TestTest : MonoBehaviour { private void Start() { } }