- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在开发一个客户端/服务器应用程序,它需要根据硬盘序列号和物理适配器 MAC 地址为每个注册客户端分配一个唯一标识符...但我不喜欢使用 ManagementObjectSearcher 或任何 WMI 解决方案,因为它们很慢。如何使用 native 方法获取这些值?
最佳答案
如果您想从硬件值中获取唯一标识符,您必须记住,对每个注册客户端始终应用相同的方法非常重要。我的意思是,如果一台机器有多个硬盘驱动器,而且这种情况很常见,您将始终必须为每个人从第一个或最后一个硬盘中取出序列号。除非您这样做只是为了许可目的,否则您还必须实现一种能够理解用户是否更改了其计算机的一个或多个组件的容差算法。我将向您展示我通常用来从硬件值中创建唯一标识符的代码……它可能有点过时,特别是对于 64x 支持(尤其是注册表键和指针),但这只是为了给您一个想法。指纹是使用 native 方法从第一个硬盘序列号、第一个适配器 MAC 地址和 SMBIOS 数据创建的。
public static class HardwareAnalyzer
{
#region Methods: Imports
[DllImport("Iphlpapi.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
internal static extern Int32 GetAdaptersInfo(IntPtr handle, ref UInt32 size);
[DllImport("Kernel32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern Boolean CloseHandle([In] IntPtr handle);
[DllImport("Kernel32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern Boolean DeviceIoControl([In] IntPtr handle, [In] UInt32 controlCode, [In, Optional] IntPtr bufferIn, [In] UInt32 bufferInSize, [Out, Optional] IntPtr bufferOut, [In] UInt32 bufferOutSize, [Out] out UInt32 bytesReturned, [In, Out, Optional] IntPtr overlapped);
[DllImport("Kernel32.dll", CharSet = CharSet.Unicode, ExactSpelling = false, SetLastError = true)]
internal static extern IntPtr CreateFile([In] String fileName, [In] eFileAccess fileAccess, [In] EFileShare fileShare, [In, Optional] IntPtr fileSecurity, [In] eCreationDisposition creationDisposition, [In] UInt32 flags, [In, Optional] IntPtr handleTemplateFile);
#endregion
#region Methods: Functions
private static String RetrieveDiskSerial()
{
String serial = String.Empty;
try
{
IntPtr handle = IntPtr.Zero;
for (Int32 i = 0; i < 16; ++i)
{
handle = CreateFile(String.Format("\\\\.\\PhysicalDrive{0}", i), (eFileAccess.GenericRead | eFileAccess.GenericWrite), (EFileShare.Read | EFileShare.Write), IntPtr.Zero, eCreationDisposition.OpenExisting, 0, IntPtr.Zero);
if (handle != IntPtr.Zero)
{
serial = RetrieveDiskSerialSmart(handle);
if (serial.Length == 0)
serial = RetrieveDiskSerialStorageQuery(handle);
if (serial.Length == 0)
continue;
if (!CloseHandle(handle))
Console.WriteLine("WARNING: a file handle has not been correctly closed.");
break;
}
}
}
catch { }
return serial;
}
private static String RetrieveDiskSerialSmart(IntPtr handle)
{
IntPtr bufferIn = Marshal.AllocHGlobal(32);
IntPtr bufferOut = Marshal.AllocHGlobal(24);
String serial = String.Empty;
UInt32 bytesReturned = 0;
try
{
if (DeviceIoControl(handle, 0x074080, IntPtr.Zero, 0, bufferOut, 24, out bytesReturned, IntPtr.Zero))
{
if ((Marshal.ReadInt32(bufferOut, 4) & 4) > 0)
{
SCInputParameters parameters = new SCInputParameters();
bufferOut = Marshal.ReAllocHGlobal(bufferOut, (IntPtr)528);
Marshal.StructureToPtr(parameters, bufferIn, true);
if (DeviceIoControl(handle, 0x07C088, bufferIn, 32, bufferOut, 528, out bytesReturned, IntPtr.Zero))
{
String serialANSI = Marshal.PtrToStringAnsi((IntPtr)(bufferOut.ToInt32() + 36), 20);
if (serialANSI.Length != 0)
{
Char[] serialANSICharacters = serialANSI.ToCharArray();
for (Int32 i = 0; i <= (serialANSICharacters.Length - 2); i += 2)
{
Char current = serialANSICharacters[i];
serialANSICharacters[i] = serialANSICharacters[(i + 1)];
serialANSICharacters[(i + 1)] = current;
}
serial = new String(serialANSICharacters).Trim();
}
}
}
}
}
finally
{
Marshal.FreeHGlobal(bufferIn);
Marshal.FreeHGlobal(bufferOut);
}
return serial;
}
private static String RetrieveDiskSerialStorageQuery(IntPtr handle)
{
IntPtr bufferIn = Marshal.AllocHGlobal(12);
IntPtr bufferOut = Marshal.AllocHGlobal(1024);
StoragePropertyQuery query = new StoragePropertyQuery();
String serial = String.Empty;
UInt32 bytesReturned = 0;
try
{
Marshal.StructureToPtr(query, bufferIn, true);
if (DeviceIoControl(handle, 0x2D1400, bufferIn, 12, bufferOut, 1024, out bytesReturned, IntPtr.Zero))
{
Int32 address = bufferOut.ToInt32();
Int32 offset = Marshal.ReadInt32(bufferOut, 24);
if (offset != 0)
{
String serialANSI = Marshal.PtrToStringAnsi((IntPtr)(address + offset));
if (serialANSI.Length != 0)
{
StringBuilder builder = new StringBuilder();
for (Int32 i = 0; i < serialANSI.Length; i += 4)
{
for (Int32 j = 1; j >= 0; --j)
{
Int32 sum = 0;
for (Int32 y = 0; y < 2; ++y)
{
sum *= 16;
switch (serialANSI[(i + (j * 2) + y)])
{
case '0':
sum += 0;
break;
case '1':
sum += 1;
break;
case '2':
sum += 2;
break;
case '3':
sum += 3;
break;
case '4':
sum += 4;
break;
case '5':
sum += 5;
break;
case '6':
sum += 6;
break;
case '7':
sum += 7;
break;
case '8':
sum += 8;
break;
case '9':
sum += 9;
break;
case 'a':
sum += 10;
break;
case 'b':
sum += 11;
break;
case 'c':
sum += 12;
break;
case 'd':
sum += 13;
break;
case 'e':
sum += 14;
break;
case 'f':
sum += 15;
break;
}
}
if (sum > 0)
builder.Append((Char)sum);
}
}
serial = builder.ToString().Trim();
}
}
}
}
finally
{
Marshal.FreeHGlobal(bufferIn);
Marshal.FreeHGlobal(bufferOut);
}
return serial;
}
private static String RetrieveMACAddress()
{
String address = String.Empty;
try
{
UInt32 size = 0;
Int32 result = GetAdaptersInfo(IntPtr.Zero, ref size);
if ((result == 0) || (result == 111))
{
IntPtr buffer = Marshal.AllocHGlobal((IntPtr)size);
result = GetAdaptersInfo(buffer, ref size);
if (result == 0)
{
while (true)
{
String adapterName = Marshal.PtrToStringAnsi((IntPtr)(buffer.ToInt32() + 8));
IntPtr handle = CreateFile(String.Format("\\\\.\\{0}", adapterName), (eFileAccess.GenericRead | eFileAccess.GenericWrite), (EFileShare.Read | EFileShare.Write), IntPtr.Zero, eCreationDisposition.OpenExisting, 0, IntPtr.Zero);
if (handle != IntPtr.Zero)
{
IntPtr bufferIn = GCHandle.Alloc(0x1010101, GCHandleType.Pinned).AddrOfPinnedObject();
IntPtr bufferOut = Marshal.AllocHGlobal(6);
UInt32 bytesReturned = 0;
try
{
if (DeviceIoControl(handle, 0x170002, bufferIn, 4, bufferOut, 6, out bytesReturned, IntPtr.Zero))
{
String temporaryAddress = String.Empty;
for (Int32 i = 0; i < 6; ++i)
temporaryAddress += Marshal.ReadByte(bufferOut, i).ToString("X2") + ((i == 5) ? "" : ":");
if (temporaryAddress != "00:00:00:00:00:00")
{
address = temporaryAddress;
break;
}
}
}
finally
{
if (!CloseHandle(handle))
Console.WriteLine("WARNING: a file handle has not been correctly closed.");
Marshal.FreeHGlobal(bufferOut);
}
}
Int32 nextAdapterOffset = Marshal.ReadInt32(buffer);
if (nextAdapterOffset != 0)
buffer = (IntPtr)nextAdapterOffset;
else
break;
}
}
}
}
catch { }
return address;
}
private static String RetrieveSMBiosData()
{
String data = String.Empty;
try
{
using (RegistryKey key = Registry.LocalMachine.OpenSubKey(@"System\CurrentControlSet\Services\MSSMBios\Data", false))
{
if (key != null)
{
Byte[] keyData = (Byte[])key.GetValue("SMBiosData");
if (keyData != null)
{
using (MD5CryptoServiceProvider provider = new MD5CryptoServiceProvider())
keyData = provider.ComputeHash(keyData);
for (Int32 i = 0; i < keyData.Length; ++i)
data += keyData[i].ToString("X2");
}
}
}
}
catch { }
return data;
}
public static String CreateFingerprint()
{
String serial = RetrieveDiskSerial();
String address = RetrieveMACAddress();
String data = RetrieveSMBiosData();
if ((serial.Length == 0) && (address.Length == 0) && (data.Length == 0))
return "0000-0000-0000-0000-0000-0000-0000-0000";
String fingerprint = String.Empty;
using (MD5CryptoServiceProvider provider = new MD5CryptoServiceProvider())
{
Byte[] hash = provider.ComputeHash(Encoding.ASCII.GetBytes(serial + " - " + address + " - " + data));
for (Int32 i = 0; i < 16; ++i)
{
fingerprint += hash[i].ToString("X2");
if (((i & 1) != 0) && (i != 15))
fingerprint += "-";
}
}
return fingerprint;
}
#endregion
#region Nesting: Enumerators
public enum eCreationDisposition : uint
{
New = 1,
CreateAlways = 2,
OpenExisting = 3,
OpenAlways = 4,
TruncateExisting = 5
}
[Flags]
public enum eFileAccess : uint
{
Delete = 0x00010000,
ReadControl = 0x00020000,
WriteDAC = 0x00040000,
WriteOwner = 0x00080000,
Synchronize = 0x00100000,
AccessSystemSecurity = 0x01000000,
MaximumAllowed = 0x02000000,
GenericAll = 0x10000000,
GenericExecute = 0x20000000,
GenericWrite = 0x40000000,
GenericRead = 0x80000000
}
[Flags]
public enum EFileShare : uint
{
None = 0x00000000,
Read = 0x00000001,
Write = 0x00000002,
Delete = 0x00000004
}
#endregion
#region Nesting: Structures
[StructLayout(LayoutKind.Sequential)]
private class SCInputParameters
{
private int BufferSize = 528;
private Byte Features = 0;
private Byte SectorCount = 1;
private Byte SectorNumber = 1;
private Byte LowOrderCylinder = 0;
private Byte HighOrderCylinder = 0;
private Byte DriveHead = 160;
private Byte Command = 236;
private Byte Reserved = 0;
private Byte DriveNumber = 0;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
private Byte[] UselessData = new Byte[16];
}
[StructLayout(LayoutKind.Sequential)]
private class StoragePropertyQuery
{
private Int32 PropertyID;
private Int32 QueryType;
private Int32 UselessData;
}
#endregion
}
您只需调用 HardwareAnalyzer.CreateFingerprint() 即可获得所需内容。
关于c# - 检索硬盘序列号和物理 MAC 地址的最快方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14329673/
我创建了一个具有高级非托管磁盘配置的 Azure RM VM。我有 1 个 127GB 的操作系统磁盘和一个大小为 56GB 的临时磁盘。我的操作系统磁盘还包含 SQL Server 和 ShareP
我正在开发一个目录树比较工具,它可以跨多台计算机工作,通过 TCP 与其他实例通信。 该工具运行良好,但到目前为止一直依赖于可由用户更改的驱动器号和标签。可移动驱动器是另一个问题。 我想通过某种唯一的
我正在使用硬盘 ID 为我的软件生成许可证 key 。在我的机器中,我得到 15 个字符长度的 ID。所有制造商的硬盘 ID 的这个长度是恒定的还是在它们之间变化? 是否有任何公认的方法来解释硬盘 I
本文实例讲述了java实现获取cpu、内存、硬盘、网络等信息的方法。分享给大家供大家参考,具体如下: 1. 下载安装sigar-1.6.4.zip 使用java自带的包获取系统数据,容易找不到包
我正在探索将 Aerospike 作为键值数据库,并将数据存储在磁盘上以确保安全。请确认,我理解正确: 如果在命名空间配置中我设置: 存储引擎设备 内存大小4G 文件/opt/aerospike/da
看着海藻,想换minio。主要原因 - 海藻可以很容易地用任意数量的节点/磁盘扩大。 但是对我的基础设施有几个问题。现在我有 2 个节点,每个节点有 100 个硬盘(HPE CL5800),它们被包含
我目前正在编写一个 CUDA 应用程序,并且遇到了一些“喂养野兽”的 IO 问题。 我想知道是否有任何方法可以直接从 RAID Controller 或 NIC 读取数据并将该数据直接发送到 GPU。
如何衡量文件(硬盘)I/O 的特性?例如,在具有硬盘(速度 X)和 cpu i7(或任何数量的内核)和 Y 数量的 ram(使用 Z Hz BIOS)的机器上(在 Windows 操作系统上): 可以
就像标题一样,我在裸机主机上安装了 RancherOS 并且想要 动态处理外部 USB 硬盘的添加/移除。它应该可以作为其他容器的绑定(bind)挂载访问。 最佳答案 你可以这样做: # udev_c
我想实现以下目标。 这样做的目的是让用户能够从他/她的硬盘驱动器中选择一个文件。 而没有上传的原因当然是传输成本和存储配额。没有理由保存文件。 这可能吗? 最佳答案 可以播放本地视频文件。 当
我想实现以下目标。 这样做的目的是让用户能够从他/她的硬盘驱动器中选择一个文件。 而没有上传的原因当然是传输成本和存储配额。没有理由保存文件。 这可能吗? 最佳答案 可以播放本地视频文件。 当
对于这些实例,在 C++ 运行时,有人可以大致说明什么是什么(硬盘、RAM、堆栈或堆): 局部/全局变量 类、方法和函数 指针 对象 堆栈/堆是否都位于物理 RAM 中? 如果有人可以在答案中包含硬件
我是 Synology 的新手。我想要访问我的 Synology NAS 驱动器。我遵循 Synology_Download_Station_Official_API。 我阅读了基本工作示例以获取 A
我想知道Linux(特别是树莓派)是否可以实现将我的有线电视接收器连接到我的树莓派(主/从?)有线电视接收器认为树莓派是硬盘但同时允许网络中的客户端获取录制的电影(当然不是正在录制的电影) 我猜 WD
由于我在本地主机上构建了许多虚拟网络,并且 htdocs 文件夹中的数据每天都在增加。 我想将 htdocs 文件夹移动到外部硬盘,可以这样做吗? 我尝试编辑 httpd.conf 文件。但是当我打开
我是一名优秀的程序员,十分优秀!