今天看到一个比较有意思的需求.
java实现获取win系统最近一次关机时间.
这里先谈一下解决思路,有问题先百度.经过百度介绍,我们知道win系统关机时间会以日志的形式记录下来,以win10为例在我的电脑右键->管理->计算机管理(本地)->系统工具->事件查看器->windows日志->系统,入下图所示:
随后根据百度查询到的事件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)
选择事件和日志排序,即可获取最近一次电脑关机事件
只吃我们已通过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系统官方自带日志查询查到的结果一直
这就是解决此次需求的过程,总结一下即为分析需求,依靠百度,理解吸收他人代码为己所用.