
在 Windows 系统中,获取设备唯一性标识及定位信息对设备管理、安全监控等场景意义重大。本文介绍 Java 中几种实现方法,如 JNA 库、WMI4Java 库及通过 JNI 结合 Windows API。

在 Windows 系统中,DEVPKEY_Device_ContainerId是获取设备容器唯一标识符的属性键。设备容器含多个相关设备,此标识符可区分不同设备集合。Java 无直接获取该属性的方法,可借助 JNA (Java Native Access)库访问 Windows 底层接口实现读取。
若用 Maven 管理项目,在pom.xml添加如下依赖。
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>5.13.0</version>
</dependency>以下是读取DEVPKEY_Device_ContainerId的示例代码。代码中的{设备容器路径}要换成实际在注册表中的路径(类似{数字和字母组合},可查看 Windows 注册表确定)。此代码用Advapi32Util类的registryGetStringValue方法从注册表读取指定键值对应的字符串值,访问HKEY_LOCAL_MACHINE下特定路径获取DEVPKEY_Device_ContainerId对应的设备容器唯一标识符。
import com.sun.jna.platform.win32.Advapi32Util;
import com.sun.jna.platform.win32.WinReg;
public class WindowsDeviceIdReader {
public static void main(String[] args) {
String containerId = Advapi32Util.registryGetStringValue(
WinReg.HKEY_LOCAL_MACHINE,
"SYSTEM\\CurrentControlSet\\Control\\DeviceContainers\\{设备容器路径}\\Properties",
"{DEVPKEY_Device_ContainerId}"
);
System.out.println("设备容器ID: " + containerId);
}
}Windows Management Instrumentation(WMI)是微软管理技术,可供管理员和开发者统一查询与管理 Windows 系统资源,包括硬件设备、软件组件等。WMI4Java 库为 Java 程序访问 WMI 提供便捷途径。
若用 Maven 管理项目,在pom.xml添加如下依赖。
<dependency>
<groupId>org.boris.winrun4j</groupId>
<artifactId>wmi4java</artifactId>
<version>1.5.0</version>
</dependency>先创建“WMI”对象,获取“Win32_PhysicalMedia”类实例,该类含物理设备(如硬盘)信息,遍历可获设备序列号这一唯一性标识。不同设备类(如“Win32_NetworkAdapter”用于网络适配器)能提供不同设备标识信息。
import org.boris.winrun4j.wmi.WMI;
import org.boris.winrun4j.wmi.WMIException;
import org.boris.winrun4j.wmi.WMIClass;
import org.boris.winrun4j.wmi.WMIObject;
public class WMIDeviceIdReader {
public static void main(String[] args) {
try {
WMI wmi = new WMI();
// 查询Win32_PhysicalMedia类获取设备信息
WMIClass c = wmi.getWMIClass("Win32_PhysicalMedia");
for (WMIObject o : c.instances()) {
String serialNumber = o.get("SerialNumber").toString();
System.out.println("设备序列号(唯一性标识之一): " + serialNumber);
}
} catch (WMIException e) {
e.printStackTrace();
}
}
}JNI 允许 Java 代码与其他语言(如 C/C++)编写的代码交互。Windows 提供了一系列 API 用于获取设备信息,例如SetupDiGetDeviceInstanceId函数可获取设备实例 ID,这是设备的一种唯一性标识。
C++获取设备实例 ID 示例。代码先通过SetupDiGetClassDevs获取设备信息集,再用SetupDiEnumDeviceInfo和SetupDiGetDeviceInstanceId获取首个设备实例 ID 存于传入缓冲区。
#include <windows.h>
#include <setupapi.h>
#include <stdio.h>
extern "C" {
__declspec(dllexport) void getDeviceInstanceId(char* buffer, DWORD bufferSize) {
HDEVINFO deviceInfoSet = SetupDiGetClassDevs(NULL, NULL, NULL, DIGCF_PRESENT);
if (deviceInfoSet == INVALID_HANDLE_VALUE) {
return;
}
SP_DEVINFO_DATA deviceInfoData;
deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
if (SetupDiEnumDeviceInfo(deviceInfoSet, 0, &deviceInfoData)) {
DWORD requiredSize;
SetupDiGetDeviceInstanceId(deviceInfoSet, &deviceInfoData, buffer, bufferSize, &requiredSize);
}
SetupDiDestroyDeviceInfoList(deviceInfoSet);
}
}使用 Visual C++编译器时,可在命令行执行cl /LD getDeviceInstanceId.cpp(代码存于该文件)进行编译,编译步骤因编译器而异。
Java 示例代码:用System.loadLibrary加载编译好的 DLL,定义本地方法getDeviceInstanceId,在main方法中调用该方法获取设备实例 ID,注意替换yourDLLName为实际 DLL 名称。
class DeviceIdJNI {
static {
System.loadLibrary("yourDLLName"); // 替换为实际的DLL名称
}
public native void getDeviceInstanceId(byte[] buffer, int bufferSize);
public static void main(String[] args) {
DeviceIdJNI deviceIdJNI = new DeviceIdJNI();
byte[] buffer = new byte[1024];
deviceIdJNI.getDeviceInstanceId(buffer, buffer.length);
String deviceInstanceId = new String(buffer).trim();
System.out.println("设备实例ID: " + deviceInstanceId);
}
}原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。