• 记MAC地址、磁盘序列号的获取


    import java.io.*;
    import java.net.Inet4Address;
    import java.net.InetAddress;
    import java.net.NetworkInterface;
    import java.net.SocketException;
    import java.util.*;
    
    /**
     * 注意事项:
     * ① 通过执行vbs 脚本(基于微软 Visual Basic的脚本语言) 来获取信息的方式只适用于windows系统,因为这种方式极度依赖 Windows脚本宿主环境的支持
     * ② 关于临时目录,可通过 System.getProperty("java.io.tmpdir") 获取其具体位置。在window下通常为 C:UsersAdministratorAppDataLocalTemp ,linux系统 下为 /tmp
     * ③ 命令方式和执行vbs 脚本的方式获取到的磁盘序列号并不相同,具体哪个是真实的序列号,有待验证
     * ④ 或可尝试通过arp 命令来获取物理地址,但是arp查询的是高速缓存表的IP-MAC映射关系,包括了网络中与本机通信过的所有主机的MAC-IP映射关系(你可以ping一下远程主机建立相应的映射关系缓存),获取的地址信息或显得过于庞杂
     * ⑤ 针对 Linux 系统主要通过执行命令的方式,不过由于系统架构的差异性,不同平台对同样的命令不一定都支持,需要根据具体系统测试、做兼容,这里提供一些常用查看命令——
     *     MAC 地址:ip link | grep link/ether | awk '{print $2}'
     *     磁盘序列号 hdparm -i /dev/sda | grep SerialNo  或  lsblk  -a -o SERIAL
     *     CPU序列号 dmidecode -t processor | grep 'ID'
     */
    
    public class NetworkUtil {
        /**
         * 通过执行vbs 脚本获取系统主板序列号
         */
        public static String getMotherboardSerialByVbs() {
            StringBuilder result = new StringBuilder();
            try {
                File file = File.createTempFile("realhowto", ".vbs");
                file.deleteOnExit();
                FileWriter fw = new FileWriter(file);
                String vbs = "Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")
    "
                        + "Set colItems = objWMIService.ExecQuery _ 
    "
                        + "   ("Select * from Win32_BaseBoard") 
    "
                        + "For Each objItem in colItems 
    "
                        + "    Wscript.Echo objItem.SerialNumber 
    "
                        + "    exit for  ' do the first cpu only! 
    "
                        + "Next 
    ";
                fw.write(vbs);
                fw.close();
                // Nologo   无标识执行 vbs 脚本
                Process p = Runtime.getRuntime().exec("cscript //NoLogo " + file.getPath());
                BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
                String line;
                while ((line = input.readLine()) != null) {
                    result.append(line);
                }
                input.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return result.toString().trim();
        }
    
        /**
         * 通过执行 vbs 脚本(基于微软 Visual Basic的脚本语言) 来获磁盘序列号
         */
        public static String getWindowsDiskSerialByVbs() {
            StringBuilder result = new StringBuilder();
            try {
                // 默认目录下创建临时文件,自己在任意位置创建vbs文件执行都可以
                File file = File.createTempFile("tmp", ".vbs");
                // 虚拟机退出时删除临时目录
                file.deleteOnExit();
                FileWriter fw = new FileWriter(file);
                String vbs = "Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")
    "
                        + "Set colItems = objWMIService.ExecQuery _ 
    "
                        + "   ("Select * from Win32_BaseBoard") 
    "
                        + "For Each objItem in colItems 
    "
                        + "    Wscript.Echo objItem.SerialNumber 
    "
                        + "    exit for  ' do the first cpu only! 
    " + "Next 
    ";
                fw.write(vbs);
                fw.flush();
                fw.close();
                Process p = Runtime.getRuntime().exec("cscript //NoLogo " + file.getPath());
                BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
                String line;
                while ((line = input.readLine()) != null) {
                    result.append(line);
                }
                input.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return result.toString().trim();
        }
    
        /**
         * 通过 vbs 脚本获取分区标记序列号,该序列号是由操作系统在格式化驱动器时创建的,而不是制造商的硬件序列号。 可参见 https://www.rgagnon.com/javadetails/java-0580.html
         */
        public static String getWindowsDiskSerialByVbs(String drive) {
            StringBuilder result = new StringBuilder();
            try {
                File file = File.createTempFile("tmp", ".vbs");
                file.deleteOnExit();
                FileWriter fw = new java.io.FileWriter(file);
                String vbs = "Set objFSO = CreateObject("Scripting.FileSystemObject")
    "
                        + "Set colDrives = objFSO.Drives
    "
                        + "Set objDrive = colDrives.item("" + drive + "")
    "
                        + "Wscript.Echo objDrive.SerialNumber";
                fw.write(vbs);
                fw.close();
                Process p = Runtime.getRuntime().exec("cscript //NoLogo " + file.getPath());
                BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
                String line;
                while ((line = input.readLine()) != null) {
                    result.append(line);
                }
                input.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return result.toString().trim();
        }
    
        /**
         * 通过 cmd 命令获取序列号,不同Windows系统系统获取的序列号格式不尽一致,请自行测试
         * ① 获取 磁盘 序列号
         * wmic diskdrive get Serialnumber
         * wmic path win32_physicalmedia get SerialNumber
         * wmic path Win32_DiskDrive get SerialNumber
         * ② 获取 主板 序列号
         * wmic baseboard get Serialnumber
         * ③ 获取 CPU 序列号
         * wmic cpu get processorid
         */
        public static String getWindowsSerialByCmd(String cmd) {
            try {
                Process process = Runtime.getRuntime().exec(cmd);
                InputStream inputStream = process.getInputStream();
                Scanner scanner = new Scanner(inputStream);
                scanner.next();
                return scanner.next();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
            return "";
        }
    
        /**
         *  在 Linux 上获取序列号
         *  lsblk  -a -o SERIAL 在红帽系统(Red Hat)和基于红帽的CentOS虚拟机系统, 龙芯系统(mips64)上可以成功获取,但在 arm 系统 armv7l 等架构的某些机器中无法成功获取 不同平台获取的格式需要进行针对性的处理
         */
        public static String getDiskSerial(String cmd) {
            String execResult = getLinuxSerialByCmd(cmd);
            if (execResult == null)
                throw new RuntimeException("设备不支持该命令获取!");
            String[] infos = execResult.split("
    ");
            if (infos.length > 1) {
                return infos[infos.length - 1];
            }
            return null;
        }
    
    
        /**
         * 获取本地主机所有 IPv4 地址列表
         * 注意事项: 由于NetworkInterface 只能枚举已启用的网卡信息,所以该方法只能获取到设备上已启用的网卡的 IP 地址
         */
        public static List<String> getLocalHostIPv4Addr() throws SocketException {
            List<String> ips = new ArrayList<>();
            // 本机所有网络接口列表 这里有个坑,枚举出来的其实只是已经启用的网络接口 ,在Linux系统上也即 ifconfig 能看到的,通过 ip link 才能查看所有网络接口
            Enumeration<NetworkInterface> enums = NetworkInterface.getNetworkInterfaces();
            while (enums.hasMoreElements()) {
                NetworkInterface networkInterface = enums.nextElement();
                // 枚举网络接口上所有地址的列表 一个网络接口可以绑定多个IP地址
                Enumeration<InetAddress> addres = networkInterface.getInetAddresses();
                while (addres.hasMoreElements()) {
                    InetAddress inetAddress = addres.nextElement();
                    // 只查询IPv4地址接口,排除了IPv6和回送地址
                    String hostAddress = inetAddress.getHostAddress();
                    if (inetAddress instanceof Inet4Address && !"127.0.0.1".equals(hostAddress)) {
                        ips.add(hostAddress);
                    }
                }
            }
            return ips;
        }
    
    
        /**
         * 根据 IP 获取物理地址
         *
         * @param bytes 原始 IP
         * @return mac 地址
         */
        public static String getMacByIp(byte[] bytes) {
            try {
                InetAddress inetAddress = InetAddress.getByAddress(bytes);
                NetworkInterface networkInterface = NetworkInterface.getByInetAddress(inetAddress);
                byte[] hardwareAddress = networkInterface.getHardwareAddress();
                return formartMac(hardwareAddress);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    
        /**
         * 根据 IP 获取物理地址
         *
         * @param ip 点分四段 IP 地址
         * @return mac 地址
         */
        public static String getMacByIp(String ip) {
            try {
                InetAddress inetAddress = InetAddress.getByName(ip);
                NetworkInterface networkInterface = NetworkInterface.getByInetAddress(inetAddress);
                byte[] hardwareAddress = networkInterface.getHardwareAddress();
                return formartMac(hardwareAddress);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    
    
        /**
         * 根据 网卡名 获取物理地址
         *
         * @param eth 网卡名
         * @return mac 地址
         */
        public static String getMacByNetCard(String eth) {
            try {
                NetworkInterface networkInterface = NetworkInterface.getByName(eth);
                byte[] hardwareAddress = networkInterface.getHardwareAddress();
                return formartMac(hardwareAddress);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    
    
        /**
         * mac 地址格式化
         */
        private static String formartMac(byte[] bytes) {
            if (bytes == null || bytes.length == 0)
                return "";
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < bytes.length; i++) {
                if (i != 0) {
                    sb.append("-");
                }
                String temp = Integer.toHexString(bytes[i] & 0xFF);
                sb.append(temp.length() == 1 ? (0 + temp) : temp);
            }
            return sb.toString().toUpperCase();
        }
    
    
        /**
         *  命令执行
         */
        private static String getLinuxSerialByCmd(String cmd) {
            try {
                Runtime run = Runtime.getRuntime();
                Process process = run.exec(cmd);
                InputStream in = process.getInputStream();
                StringBuilder sb = new StringBuilder();
                byte[] b = new byte[1024];
                for (int n; (n = in.read(b)) != -1;) {
                    sb.append(new String(b, 0, n));
                }
                in.close();
                process.destroy();
                return sb.toString();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    
    }
  • 相关阅读:
    「日常报错」Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
    LeetCode1026. 节点与其祖先之间的最大差值
    Erlang TCP 实例
    「笔记」Systemd 的基础
    折腾日记「乱七八糟的过程」
    LeetCode15.三数之和
    Sql Paging
    行变列
    SQL JOINS
    DBML存储过程返回值
  • 原文地址:https://www.cnblogs.com/chenbenbuyi/p/11441112.html
Copyright © 2020-2023  润新知