67

我想获得一个具有 Java、Windows、MacOS 以及(如果可能的话)Linux 的计算机的唯一 ID。它可能是磁盘 UUID、主板 S/N...

Runtime.getRuntime().exec可以使用(它不是小程序)。

想法?

4

11 回答 11

51

MAC地址的问题是可以有许多网络适配器连接到计算机。大多数最新的默认情况下都有两个(wi-fi + 电缆)。在这种情况下,必须知道应该使用哪个适配器的 MAC 地址。我在我的系统上测试了 MAC 解决方案,但我有 4 个适配器(用于 Virtual Box 的电缆、WiFi、TAP 适配器和一个用于蓝牙),我无法决定我应该使用哪个 MAC... 如果有人决定使用适配器当前正在使用(已分配地址)然后出现新问题,因为有人可以拿起他/她的笔记本电脑并从电缆适配器切换到wi-fi。在这种情况下,当笔记本电脑通过电缆连接时存储的 MAC 现在将无效。

例如,这些是我在系统中找到的适配器:

lo MS TCP Loopback interface
eth0 Intel(R) Centrino(R) Advanced-N 6205
eth1 Intel(R) 82579LM Gigabit Network Connection
eth2 VirtualBox Host-Only Ethernet Adapter
eth3 Sterownik serwera dostepu do sieci LAN Bluetooth

我用来列出它们的代码:

Enumeration<NetworkInterface> nis = NetworkInterface.getNetworkInterfaces();
while (nis.hasMoreElements()) {
    NetworkInterface ni = nis.nextElement();
    System.out.println(ni.getName() + " " + ni.getDisplayName());
}

从这个页面上收听的选项中,我最能接受的,我在我的解决方案中使用的一个是@Ozhan Duz 的一个,另一个类似于@finnw 的答案,他使用了 JACOB,值得一提的是com4j - 使用 WMI 的示例可在此处获得:

ISWbemLocator wbemLocator = ClassFactory.createSWbemLocator();
ISWbemServices wbemServices = wbemLocator.connectServer("localhost","Root\\CIMv2","","","","",0,null);
ISWbemObjectSet result = wbemServices.execQuery("Select * from Win32_SystemEnclosure","WQL",16,null);
for(Com4jObject obj : result) {
    ISWbemObject wo = obj.queryInterface(ISWbemObject.class);
    System.out.println(wo.getObjectText_(0));
}

这将打印一些计算机信息和计算机序列号。请注意,此示例所需的所有类都必须由 maven-com4j-plugin 生成。maven-com4j-plugin 的示例配置:

<plugin>
    <groupId>org.jvnet.com4j</groupId>
    <artifactId>maven-com4j-plugin</artifactId>
    <version>1.0</version>
    <configuration>
        <libId>565783C6-CB41-11D1-8B02-00600806D9B6</libId>
        <package>win.wmi</package>
        <outputDirectory>${project.build.directory}/generated-sources/com4j</outputDirectory>
    </configuration>
    <executions>
        <execution>
            <id>generate-wmi-bridge</id>
            <goals>
                <goal>gen</goal>
            </goals>
        </execution>
    </executions>
</plugin>

上面的配置将告诉插件在项目文件夹的 target/generated-sources/com4j 目录中生成类。

对于那些希望看到即用型解决方案的人,我提供了指向我为在 Windows、Linux 和 Mac OS 上获取机器 SN 而编写的三个类的链接:

于 2012-10-17T16:42:08.363 回答
34

OSHI项目提供独立于平台的硬件实用程序。

Maven依赖:

<dependency>
    <groupId>com.github.oshi</groupId>
    <artifactId>oshi-core</artifactId>
    <version>LATEST</version>
</dependency>

例如,您可以使用类似以下代码的代码来唯一标识一台机器:

import oshi.SystemInfo;
import oshi.hardware.CentralProcessor;
import oshi.hardware.ComputerSystem;
import oshi.hardware.HardwareAbstractionLayer;
import oshi.software.os.OperatingSystem;

class ComputerIdentifier
{
    static String generateLicenseKey()
    {
        SystemInfo systemInfo = new SystemInfo();
        OperatingSystem operatingSystem = systemInfo.getOperatingSystem();
        HardwareAbstractionLayer hardwareAbstractionLayer = systemInfo.getHardware();
        CentralProcessor centralProcessor = hardwareAbstractionLayer.getProcessor();
        ComputerSystem computerSystem = hardwareAbstractionLayer.getComputerSystem();

        String vendor = operatingSystem.getManufacturer();
        String processorSerialNumber = computerSystem.getSerialNumber();
        String processorIdentifier = centralProcessor.getIdentifier();
        int processors = centralProcessor.getLogicalProcessorCount();

        String delimiter = "#";

        return vendor +
                delimiter +
                processorSerialNumber +
                delimiter +
                processorIdentifier +
                delimiter +
                processors;
    }

    public static void main(String[] arguments)
    {
        String identifier = generateLicenseKey();
        System.out.println(identifier);
    }
}

我的机器的输出:

Microsoft#57YRD12#Intel64 Family 6 Model 60 Stepping 3#8

您的输出会有所不同,因为至少处理器序列号会有所不同。

于 2016-06-08T14:17:24.823 回答
22

通常使用 MAC 地址与网卡相关联。

该地址可通过以下 API 在 Java 6 中使用:

硬件地址的 Java 6 文档

我没有在 Java 中使用过它,但是对于其他网络识别应用程序来说它很有帮助。

于 2009-12-31T19:31:51.083 回答
12

你想用这个唯一的 ID 做什么?没有这个ID,也许你可以做你想做的事。

MAC 地址可能是一种选择,但这不是一个受信任的唯一 ID,因为用户可以更改计算机的 MAC 地址。

要在此链接上检查主板或处理器 ID 。

于 2009-12-31T19:36:29.000 回答
9

仅在 Windows 上,您可以使用WMI通过 COM 桥(例如JACOB )获取主板 ID 。

例子:

import java.util.Enumeration;
import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.ComThread;
import com.jacob.com.EnumVariant;
import com.jacob.com.Variant;

public class Test {
    public static void main(String[] args) {
        ComThread.InitMTA();
        try {
            ActiveXComponent wmi = new ActiveXComponent("winmgmts:\\\\.");
            Variant instances = wmi.invoke("InstancesOf", "Win32_BaseBoard");
            Enumeration<Variant> en = new EnumVariant(instances.getDispatch());
            while (en.hasMoreElements())
            {
                ActiveXComponent bb = new ActiveXComponent(en.nextElement().getDispatch());
                System.out.println(bb.getPropertyAsString("SerialNumber"));
                break;
            }
        } finally {
            ComThread.Release();
        }
    }
}

而如果你选择使用MAC地址来识别机器,你可以使用WMI来判断一个接口是否是通过USB连接的(如果你想排除USB适配器的话)。

也可以通过 WMI 获取硬盘 ID,但这是不可靠的。

于 2010-01-01T14:11:21.820 回答
8

使用 MAC 地址作为标识符时要小心。我经历了几个陷阱:

  1. 在 OS X 上,未激活/启动的以太网端口不会显示在NetworkInterface.getNetworkInterfaces()枚举中。
  2. 如果您拥有适当的操作系统权限,那么更改卡上的 MAC 地址非常容易。
  3. Java 有不能正确识别“虚拟”接口的习惯。即使使用NetworkInterface.isVirtual()也不会总是告诉你真相。

即使存在上述问题,我仍然认为这是硬件锁定许可证的最佳纯 Java 方法。

于 2010-01-01T14:32:11.417 回答
8

不知道您的所有要求。例如,您是想从世界上的所有计算机中唯一地标识一台计算机,还是只是试图从您的应用程序的一组用户中唯一地标识一台计算机。另外,您可以在系统上创建文件吗?

如果您能够创建一个文件。您可以创建一个文件并将文件的创建时间用作您的唯一 ID。如果您在用户空间中创建它,那么它将在特定机器上唯一标识您的应用程序的用户。如果您在全局某个地方创建它,那么它可以唯一地识别机器。

同样,与大多数事情一样,多快就足够快......或者在这种情况下,独特性是多么独特。

于 2010-03-01T17:21:24.037 回答
2

我认为您应该查看此链接...您可以使用多个标识符制作混合密钥,例如 mac+os+hostname+ cpu id +主板序列号

于 2009-12-31T20:14:16.770 回答
1

如果任务是关于记录系统的唯一 ID,则使用MAC id 是最简单的方法。

mac id虽然可以改变,但系统其他id的改变也是可以的,就是更换相应的设备。

因此,除非不知道唯一 id 需要什么,否则我们可能无法找到合适的解决方案。

但是,下面的链接有助于提取 mac 地址。 http://www.stratos.me/2008/07/find-mac-address-using-java/

于 2012-05-29T07:06:10.153 回答
1

用于唯一识别 Windows 机器。确保在使用 wmic 时有替代方法的策略。由于“wmic bios get serialnumber”可能不适用于所有机器,您可能需要其他方法:

# Get serial number from bios
wmic bios get serialnumber
# If previous fails, get UUID
wmic csproduct get UUID
# If previous fails, get diskdrive serialnumber
wmic DISKDRIVE get SerialNumber

资源:唯一识别 Windows 机器的最佳方法 http://www.nextofwindows.com/the-best-way-to-uniquely-identify-a-windows-machine/

于 2015-05-11T15:17:41.807 回答
0

在我为发布而编写的 Java 程序中,我使用了主板序列号(这是我相信 windows 使用的);但是,这仅适用于 Windows,因为我的函数创建了一个临时 VB 脚本,该脚本使用 WMI 来检索值。

public static String getMotherboardSerial() {
      String result = "";
        try {
          File file = File.createTempFile("GetMBSerial",".vbs");
          file.deleteOnExit();
          FileWriter fw = new FileWriter(file);

          String vbs =
             "Set objWMIService = GetObject(\"winmgmts:\\\\.\\root\\cimv2\")\n"
            + "Set colItems = objWMIService.ExecQuery _ \n"
            + "   (\"Select * from Win32_ComputerSystemProduct\") \n"
            + "For Each objItem in colItems \n"
            + "    Wscript.Echo objItem.IdentifyingNumber \n"
            + "Next \n";

          fw.write(vbs);
          fw.close();
          Process gWMI = Runtime.getRuntime().exec("cscript //NoLogo " + file.getPath());
          BufferedReader input = new BufferedReader(new InputStreamReader(gWMI.getInputStream()));
          String line;
          while ((line = input.readLine()) != null) {
             result += line;
             System.out.println(line);
          }
          input.close();
        }
        catch(Exception e){
            e.printStackTrace();
        }
        result = result.trim();
        return result;
      }
于 2014-01-02T00:48:14.257 回答