using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using UnityEngine;
public class DiskID : MonoBehaviour
{
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
{
/// <summary>
/// Read SMART data.
/// </summary>
SmartReadData = 0xD0,
/// <summary>
/// Read SMART thresholds.
/// </summary>
SmartReadThresholds = 0xD1, /* obsolete */
/// <summary>
/// Autosave SMART data.
/// </summary>
SmartAutosave = 0xD2,
/// <summary>
/// Save SMART attributes.
/// </summary>
SmartSaveAttr = 0xD3,
/// <summary>
/// Set SMART to offline immediately.
/// </summary>
SmartImmediateOffline = 0xD4,
/// <summary>
/// Read SMART log.
/// </summary>
SmartReadLog = 0xD5,
/// <summary>
/// Write SMART log.
/// </summary>
SmartWriteLog = 0xD6,
/// <summary>
/// Write SMART thresholds.
/// </summary>
SmartWriteThresholds = 0xD7, /* obsolete */
/// <summary>
/// Enable SMART.
/// </summary>
SmartEnableOperations = 0xD8,
/// <summary>
/// Disable SMART.
/// </summary>
SmartDisableOperations = 0xD9,
/// <summary>
/// Get SMART status.
/// </summary>
SmartStatus = 0xDA,
/// <summary>
/// Set SMART to offline automatically.
/// </summary>
SmartAutoOffline = 0xDB, /* obsolete */
}
public enum RegisterCommand : byte
{
/// <summary>
/// SMART data requested.
/// </summary>
SmartCmd = 0xB0,
/// <summary>
/// Identify data is requested.
/// </summary>
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);
}
}
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("硬盘编号:" + 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
);
/// <summary>
/// 获取硬盘序列号
/// </summary>
/// <param name="drvID">硬盘盘符[c|d|e|....]</param>
/// <returns></returns>
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
}
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using UnityEngine;
public class DiskID : MonoBehaviour
{
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
{
/// <summary>
/// Read SMART data.
/// </summary>
SmartReadData = 0xD0,
/// <summary>
/// Read SMART thresholds.
/// </summary>
SmartReadThresholds = 0xD1, /* obsolete */
/// <summary>
/// Autosave SMART data.
/// </summary>
SmartAutosave = 0xD2,
/// <summary>
/// Save SMART attributes.
/// </summary>
SmartSaveAttr = 0xD3,
/// <summary>
/// Set SMART to offline immediately.
/// </summary>
SmartImmediateOffline = 0xD4,
/// <summary>
/// Read SMART log.
/// </summary>
SmartReadLog = 0xD5,
/// <summary>
/// Write SMART log.
/// </summary>
SmartWriteLog = 0xD6,
/// <summary>
/// Write SMART thresholds.
/// </summary>
SmartWriteThresholds = 0xD7, /* obsolete */
/// <summary>
/// Enable SMART.
/// </summary>
SmartEnableOperations = 0xD8,
/// <summary>
/// Disable SMART.
/// </summary>
SmartDisableOperations = 0xD9,
/// <summary>
/// Get SMART status.
/// </summary>
SmartStatus = 0xDA,
/// <summary>
/// Set SMART to offline automatically.
/// </summary>
SmartAutoOffline = 0xDB, /* obsolete */
}
public enum RegisterCommand : byte
{
/// <summary>
/// SMART data requested.
/// </summary>
SmartCmd = 0xB0,
/// <summary>
/// Identify data is requested.
/// </summary>
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);
}
}
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("硬盘编号:" + 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
);
/// <summary>
/// 获取硬盘序列号
/// </summary>
/// <param name="drvID">硬盘盘符[c|d|e|....]</param>
/// <returns></returns>
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
}