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

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

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

java 查询时间在某一天的数据 java中记录时间_java

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

事件id对应表如下所示

id

类型

来源

代 表 的 意 义 举 例 解 释

2

信息

Serial

在验证 \Device\Serial1 是否确实是串行口时,系统检测到先进先出方式(fifo)。将使用该方式。

17

错误

W32Time

时间提供程序 NtpClient: 在 DNS 查询手动配置的对等机器 ‘time.windows.com,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.com (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

警告

Tcpip

TCP/IP 已经达到并发 TCP 连接尝试次数的安全限制。

4377

信息

NtServicePack

Windows 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 Manager

Eset Service 服务意外地终止,这种情况已经出现了 1 次。以下的修正操作将在 0 毫秒内运行: 重新启动服务。

7035

信息

Service Control Manager

xxx服务成功发送一个开始控件。

7036

信息

Service Control Manager

xxx服务处于运行或停止等状态。

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)

java 查询时间在某一天的数据 java中记录时间_Source_02

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

java 查询时间在某一天的数据 java中记录时间_java 查询时间在某一天的数据_03

只吃我们已通过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系统官方自带日志查询查到的结果一直

java 查询时间在某一天的数据 java中记录时间_java 查询时间在某一天的数据_04


项目代码连接

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