admin管理员组

文章数量:1566353

java获取Win系统日志开关机记录等

java实现代码在后面,没耐心看的小伙伴请玩后面划拉

今天看到一个比较有意思的需求.

java实现获取win系统最近一次关机时间.

这里先谈一下解决思路,有问题先百度.经过百度介绍,我们知道win系统关机时间会以日志的形式记录下来,以win10为例在我的电脑右键->管理->计算机管理(本地)->系统工具->事件查看器->windows日志->系统,入下图所示:

随后根据百度查询到的事件ID过滤出关机事件的日志.

事件id对应表如下所示

id类型来源代 表 的 意 义 举 例 解 释
2信息Serial在验证 \Device\Serial1 是否确实是串行口时,系统检测到先进先出方式(fifo)。将使用该方式。
17错误W32Time时间提供程序 NtpClient: 在 DNS 查询手动配置的对等机器 ‘time.windows,0x1’ 时发生一个错误。 NtpClient 将在 15 分钟内重试 NDS 查询。 错误为: 套接字操作尝试一个无法连接的主机。 (0x80072751)
20警告Print已经添加或更新 Windows NT x86 Version-3 的打印机驱动程序 Canon PIXMA iP1000。文件:- CNMDR6e.DLL, CNMUI6e.DLL, CNMCP6e.DLL, CNMMH6e.HLP, CNMD56e.DLL, CNMUR6e.DLL, CNMSR6e.DLL, CNMIN6e.INI, CNMPI6e.DLL, CNMSM6e.EXE, CNMSS6e.SMR, CNMSD6e.EXE, CNMSQ6e.EXE, CNMSH6e.HLP, CNMSH6e
26信息Application Popup弹出应用程序: Rsaupd.exe - 无法找到组件: 没有找到 MFC71.DLL,因此这个应用程序未能启动。重新安装应用程序可能会修复此问题。
29错误W32Time时间服务提供程序 NtpClient 配置为从一个或多个时间源 获得时间,但是,没有一个源可以访问。在 14 分钟内不 会进行联系时间源的尝试。 NtpClient 没有准确时间的时间源。
35信息W32Time时间服务现在用时间源 time.windows (ntp.m
115信息SRService系统还原监视在所有驱动器上启用。
116信息SRService系统还原监视在所有驱动器上禁用。
1001信息Save Dump计算机已经从检测错误后重新启动。检测错误: 0x4a4b4d53 (0xc000000e, 0x01d04bf0, 0x00000010, 0x0000029a)。 已将转储的数据保存在: C:\WINDOWS\Minidump\Mini052809-01.dmp。
1005警告Dhcp您的计算机检测到网络地址为 00A21C2EFEC4 的网卡的 IP 地址 192.168.1.2 已在网络上使用。 计算机会自动获取另一个地址。
3260信息Workstation此计算机成功加入到 workgroup ‘WORKGROUP’。
4202信息Tcpip系统检测到网卡 Realtek…Family PCI Fast Ethernet NIC - 数据包计划程序微型端口 与网络断开, 而且网卡的网络配置已经释放。如果 网卡没有断开,这可能意味着它出现故障。 请与您的供应商联系以获得更新的驱动程序。
4226警告TcpipTCP/IP 已经达到并发 TCP 连接尝试次数的安全限制。
4377信息NtServicePackWindows XP Hotfix KB873339 was installed.
6005信息EventLog事件日志服务已启动。(开机)
6006信息EventLog事件日志服务已停止。(关机)
6009信息EventLog按ctrl、alt、delete键(非正常)关机
6011信息EventLog此机器的 NetBIOS 名称和 DNS 主机名从 MACHINENAME 更改为 AA。
7000错误Service Control Manager由于下列错误,npkcrypt 服务启动失败:
7031错误Service Control ManagerEset Service 服务意外地终止,这种情况已经出现了 1 次。以下的修正操作将在 0 毫秒内运行: 重新启动服务。
7035信息Service Control Managerxxx服务成功发送一个开始控件。
7036信息Service Control Managerxxx服务处于运行或停止等状态。
8033信息BROWSER由于主浏览器已经停止,浏览器在 \Device\NetBT_Tcpip_{163DE7AB-92AE-499F-8340-B6358A4597CE} 网络上进行强制性的选举。
10000错误DCOM无法启动 DCOM 服务器: {80EE4902-33A8-11D1-A213-0080C88593A5}。 错误:
15007信息HTTP成功地添加了由 URL 前缀 http://*:2869/ 标识的命名空间的保留。
60054信息Setup安装程序成功地完成了安装 Windows 内部版本 2600。
64002信息Windows File Protection试图在被保护的系统文件 c:\windows\system32\quartz.dll 上进行文件替换。 为了维护系统稳定,这个文件被还原成原始版本。 系统文件的文件版本是 6.5.2600.3497。
64008警告Windows File Protection无法验证受保护的 c:\windows\system32\quartz.dll 系统文件,原因是 Windows 文件保护中断。 请过一会儿使用 SFC 工具验证该文件的完整性。

更多win日志ID类型请参考qiufengwuxiu的博客Windows事件ID大全

本需求中我们关机事件(6006)来做筛选.选择右侧筛选当前日志,在搜索条件中输入6006(关机事件的ID)

选择事件和日志排序,即可获取最近一次电脑关机事件

只吃我们已通过win官方方式查找出了win系统最后一次关机时间,接下来我们通过JAVA代码获取关机时间.

JAVA获取win系统最后一次关机时间

首先我坦白java获取win的系统日志的解决方案及思路来源于度娘,具体参考了Winfred Hu的JNA的使用及读取windows系统日志文件(EVTX文件)(一)
这篇文章.

  • 首先创建java工程
    这里我们使用gralde构建java项目
    添加依赖

compile group: ‘junit’, name: ‘junit’, version: ‘4.10’
compile group: ‘net.java.dev.jna’, name: ‘jna’, version: ‘5.0.0’
compile group: ‘net.java.dev.jna’, name: ‘jna-platform’, version: ‘5.0.0’

  • 创建一个事件实例类,用来对应解析后的事件,并继承Comparable接口,定义排序逻辑
    java代码如下所示:
package com.sakura.win.log;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @Author: sakura
 * @Date: 2021/1/22 16:04
 */
public class Event  implements Comparable<Event> {
    private int id;
    private Date time;
    private String type;
    private String category;
    private String Source;
    private String log;
    private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    public Event(int id, Date time, String type, String category, String source, String log) {
        this.id = id;
        this.time = time;
        this.type = type;
        this.category = category;
        Source = source;
        this.log = log;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public Date getTime() {
        return time;
    }

    public void setTime(Date time) {
        this.time = time;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getCategory() {
        return category;
    }

    public void setCategory(String category) {
        this.category = category;
    }

    public String getSource() {
        return Source;
    }

    public void setSource(String source) {
        Source = source;
    }

    public String getLog() {
        return log;
    }

    public void setLog(String log) {
        this.log = log;
    }

    @Override
    public int compareTo(Event o) {
        return o.getTime().compareTo(this.getTime());
    }

    @Override
    public String toString() {
        return "Event{" +
                "id=" + id +
                ", time=" + simpleDateFormat.format(time) +
                ", type='" + type + '\'' +
                ", category='" + category + '\'' +
                ", Source='" + Source + '\'' +
                ", log='" + log + '\'' +
                '}';
    }
}

  • 编辑主函数获取win日志缓存并排序
    主函数代码如下所示
package com.sakura.win.log;

import com.sun.jna.platform.win32.Advapi32Util;
import com.sun.jna.platform.win32.WinNT;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

/**
 * @Author: sakura
 * @Date: 2021/1/22 15:34
 */
public class WinLog {
    public static void main(String[] args) {
        List<Event> eventList = new ArrayList<>();
        Advapi32Util.EventLogIterator iter = new Advapi32Util.EventLogIterator("EventLog");
        while (iter.hasNext()) {
            Advapi32Util.EventLogRecord record = iter.next();
            StringBuffer data = new StringBuffer();
            String[] str = record.getStrings();
            if (str != null) {
                for (String s : str) {
                    data.append(s);
                }
            }
            WinNT.EVENTLOGRECORD record1 = record.getRecord();
            //get event generated time
            if ((short) record.getEventId() == 6006) {
                eventList.add(new Event(Integer.valueOf((short) record.getEventId()), new Date(record1.TimeGenerated.longValue() * 1000), record.getType().toString(),
                        record1.EventCategory.toString(), record.getSource().toString(), data.toString()
                ));
            }
        }
        Collections.sort(eventList);
        eventList.forEach(System.out::println);
    }
}

运行效果下: 排序后List的第一个元素即为最近的电脑关机事件,与通过wein系统官方自带日志查询查到的结果一直

项目代码连接

这就是解决此次需求的过程,总结一下即为分析需求,依靠百度,理解吸收他人代码为己所用.

本文标签: 开关机时间系统最新日志