330 lines
9.5 KiB
C#
330 lines
9.5 KiB
C#
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
|
|
{
|
|
/// <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);
|
|
}
|
|
}
|
|
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
|
|
);
|
|
/// <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
|
|
}
|
|
public class TestTest : MonoBehaviour
|
|
{
|
|
|
|
private void Start()
|
|
{
|
|
|
|
}
|
|
} |