@daimazun/hardware-info 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +907 -0
- package/bin/OpenHardwareMonitorLib.dll +0 -0
- package/index.js +192 -0
- package/lib/allhardware.js +35 -0
- package/lib/backend-usage.js +103 -0
- package/lib/battery.js +76 -0
- package/lib/disk-watcher.js +156 -0
- package/lib/disk.js +77 -0
- package/lib/gpu.js +70 -0
- package/lib/hardware-service.js +284 -0
- package/lib/memory.js +59 -0
- package/lib/monitor.js +176 -0
- package/lib/network.js +75 -0
- package/lib/ohm-daemon.js +208 -0
- package/lib/ohm.js +41 -0
- package/lib/perfctr.js +43 -0
- package/lib/process-icon.js +76 -0
- package/lib/process-ops.js +218 -0
- package/lib/processes.js +232 -0
- package/lib/ps.js +93 -0
- package/lib/public-ip.js +124 -0
- package/lib/services.js +43 -0
- package/lib/sysinfo-daemon.js +188 -0
- package/lib/system.js +77 -0
- package/lib/usb.js +49 -0
- package/lib/win32-procs.js +241 -0
- package/package.json +50 -0
- package/scripts/get-all-hardware.ps1 +98 -0
- package/scripts/get-lhm-temp.ps1 +119 -0
- package/scripts/ohm-daemon.ps1 +141 -0
- package/scripts/sysinfo-daemon.ps1 +386 -0
- package/test/check-bugs.js +182 -0
- package/test/public/gj.pay.ali.jpg +0 -0
- package/test/public/gj.pay.wx.jpg +0 -0
- package/test/public/index.html +996 -0
- package/test/public/zdl.pay.ali.jpg +0 -0
- package/test/public/zdl.pay.wx.jpg +0 -0
- package/test/scan-encoding.js +77 -0
- package/test/server.js +255 -0
- package/test/test-all.js +180 -0
- package/test/test-daemon.js +51 -0
- package/test/test-kill-name.js +30 -0
- package/test/test-monitor.js +78 -0
- package/test/test-new-features.js +93 -0
- package/test/test-service.js +91 -0
- package/test/test-sysinfo-daemon.js +95 -0
- package/test/test.js +63 -0
package/README.md
ADDED
|
@@ -0,0 +1,907 @@
|
|
|
1
|
+
# hardware-info
|
|
2
|
+
|
|
3
|
+
> 作者:高健 <gaojianstyle@163.com>
|
|
4
|
+
|
|
5
|
+
跨平台硬件信息获取与监控库。当前已实现 Windows 平台,支持 CPU 温度/负载/频率/功耗、系统信息、内存详情、硬盘、网络、电池、显卡、USB、进程、服务、进程操作(杀进程/定位文件)、磁盘插拔监听、进程图标、后端资源占用、公网 IP 等全维度硬件数据。Linux / macOS 支持规划中。
|
|
6
|
+
|
|
7
|
+
CPU 真实核心温度通过 OpenHardwareMonitor DLL 获取(仅 311KB,零安装,用完即卸载驱动不残留),其他信息通过 Windows WMI/CIM/性能计数器获取,无需管理员。进程枚举通过 koffi 直调 Win32 API(335进程 ~28ms),杀进程使用 fkill(支持 PID/端口/名称)。
|
|
8
|
+
|
|
9
|
+
## 特性
|
|
10
|
+
|
|
11
|
+
### CPU 与硬件监控
|
|
12
|
+
- **真实核心温度** — 通过 WinRing0 驱动读 CPU MSR 寄存器(DTS),不是主板热区温度
|
|
13
|
+
- **零安装** — 仅需 `OpenHardwareMonitorLib.dll`(311KB),.NET Framework 4.5(Win10/11 自带)
|
|
14
|
+
- **不残留** — 每次调用后自动卸载 WinRing0 驱动、删除服务
|
|
15
|
+
- **三种模式** — 单次调用 / 常驻进程 / 高频监控器,按需选择
|
|
16
|
+
- **多层降级** — 非管理员时自动降级到性能计数器(ACPI 热区温度)
|
|
17
|
+
|
|
18
|
+
### 系统信息(无需管理员)
|
|
19
|
+
- **系统** — OS 版本/build、计算机制造商型号、BIOS、主板、CPU 详情、开机时长、电源计划
|
|
20
|
+
- **内存** — 使用率、物理内存条详情(型号/频率/容量/厂商)、虚拟内存、最大支持容量
|
|
21
|
+
- **硬盘** — 物理磁盘(型号/接口/固件/序列号/盘符关联)、分区(文件系统/使用率)、实时读写速度/活跃度
|
|
22
|
+
- **网络** — 网卡列表、IP/MAC/DNS、实时上下行网速、WiFi SSID/信号/频道、活跃网卡过滤
|
|
23
|
+
- **电池** — 电量、健康度、充电状态、设计/满充容量、循环次数、电源计划
|
|
24
|
+
- **显卡/显示器** — 显卡型号/显存/驱动/分辨率/刷新率、虚拟显卡识别、多显示器信息
|
|
25
|
+
- **USB** — USB 控制器、已连接 USB 设备列表
|
|
26
|
+
- **进程** — koffi 直调 Win32 API(335进程 ~28ms),支持实时 CPU%、按名称聚合(含组内实例明细)、父PID/私有内存/安装时间、排序和 Top N
|
|
27
|
+
- **进程操作** — 结束进程(fkill,支持 PID/端口号/进程名/混合数组,含子进程树)、在资源管理器中定位文件
|
|
28
|
+
- **进程查找** — 按端口号查找占用 PID(netstat 解析)、按进程名查找 PID(koffi 匹配)
|
|
29
|
+
- **磁盘插拔监听** — EventEmitter,WMI 事件监听(Win32_VolumeChangeEvent,插拔瞬间触发)+ 5s 低频轮询兜底
|
|
30
|
+
- **进程图标** — 提取 exe 关联图标(base64 PNG,批量提取,按需)
|
|
31
|
+
- **服务** — Windows 服务列表(状态/启动类型/描述/运行账户)
|
|
32
|
+
- **后端资源占用** — Node.js 进程 + 所有子进程的内存/CPU/线程占用,同步 ~5-10ms,高频安全
|
|
33
|
+
- **公网 IP** — DNS 查询为主(OpenDNS 45ms)→ Google DNS → HTTPS 三源兜底,60 秒缓存,零依赖
|
|
34
|
+
- **一键汇总** — `getAllInfo()` 并行获取全部信息,单模块失败不影响其他
|
|
35
|
+
|
|
36
|
+
## 环境要求
|
|
37
|
+
|
|
38
|
+
- **操作系统**:Windows 10 / 11(当前);Linux / macOS 规划中
|
|
39
|
+
- **Node.js**:>= 14.0.0
|
|
40
|
+
- **权限**:CPU 真实核心温度需管理员;其他信息无需管理员
|
|
41
|
+
- **.NET Framework 4.5**:Win10/11 系统自带
|
|
42
|
+
|
|
43
|
+
## 安装
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
npm install @daimazun/hardware-info
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## 项目结构
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
hardware-info/
|
|
53
|
+
├── index.js # 入口,导出全部 30+ API
|
|
54
|
+
├── package.json
|
|
55
|
+
├── README.md
|
|
56
|
+
├── bin/
|
|
57
|
+
│ └── OpenHardwareMonitorLib.dll # 311KB
|
|
58
|
+
├── lib/
|
|
59
|
+
│ ├── ps.js # 通用 PowerShell 执行工具
|
|
60
|
+
│ ├── ohm.js # CPU 温度(单次模式)
|
|
61
|
+
│ ├── ohm-daemon.js # CPU 温度(常驻进程)
|
|
62
|
+
│ ├── monitor.js # CPU 温度(高频监控器)
|
|
63
|
+
│ ├── perfctr.js # 性能计数器降级
|
|
64
|
+
│ ├── allhardware.js # OHM 全硬件传感器
|
|
65
|
+
│ ├── system.js # 系统信息
|
|
66
|
+
│ ├── memory.js # 内存详情
|
|
67
|
+
│ ├── disk.js # 硬盘详情
|
|
68
|
+
│ ├── network.js # 网络信息
|
|
69
|
+
│ ├── battery.js # 电池信息
|
|
70
|
+
│ ├── gpu.js # 显卡/显示器
|
|
71
|
+
│ ├── usb.js # USB 设备
|
|
72
|
+
│ ├── processes.js # 进程列表(双后端 koffi/wmi)
|
|
73
|
+
│ ├── win32-procs.js # koffi 直调 Win32 API 进程枚举
|
|
74
|
+
│ ├── services.js # 服务列表
|
|
75
|
+
│ ├── process-ops.js # 进程操作(killProcess/showItemInFolder/findPidsByPort/findPidsByName)
|
|
76
|
+
│ ├── process-icon.js # 进程图标提取
|
|
77
|
+
│ ├── disk-watcher.js # 磁盘插拔监听(WMI 事件 + 轮询兜底)
|
|
78
|
+
│ ├── public-ip.js # 公网 IP(DNS 查询 + 缓存)
|
|
79
|
+
│ ├── sysinfo-daemon.js # 统一常驻进程(所有模块复用一个 PowerShell)
|
|
80
|
+
│ ├── hardware-service.js # 统一常驻服务(整合所有模块)
|
|
81
|
+
│ └── backend-usage.js # 后端资源占用(Node.js + 子进程)
|
|
82
|
+
├── scripts/ # PowerShell 脚本
|
|
83
|
+
│ ├── get-lhm-temp.ps1
|
|
84
|
+
│ ├── ohm-daemon.ps1
|
|
85
|
+
│ ├── get-all-hardware.ps1
|
|
86
|
+
│ └── sysinfo-daemon.ps1
|
|
87
|
+
└── test/ # 测试文件
|
|
88
|
+
├── test.js # CPU 温度 + 全硬件基础测试
|
|
89
|
+
├── test-daemon.js # CPU 温度常驻模式性能测试
|
|
90
|
+
├── test-monitor.js # CPU 温度监控器功能测试
|
|
91
|
+
├── test-all.js # 全模块综合测试(11 个模块)
|
|
92
|
+
├── test-new-features.js # 新增功能综合测试
|
|
93
|
+
├── test-service.js # 统一常驻服务测试
|
|
94
|
+
├── test-kill-name.js # 进程名/端口杀进程测试
|
|
95
|
+
├── test-sysinfo-daemon.js # 统一常驻模式性能测试
|
|
96
|
+
├── server.js # Express 测试服务(端口 3210)
|
|
97
|
+
└── public/
|
|
98
|
+
└── index.html # Vue 3 调试仪表盘
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## 快速开始
|
|
102
|
+
|
|
103
|
+
```js
|
|
104
|
+
const { getCpuTemp, getAllInfo } = require('./index');
|
|
105
|
+
|
|
106
|
+
// CPU 温度(需管理员拿真实核心温度,非管理员自动降级)
|
|
107
|
+
const cpu = await getCpuTemp();
|
|
108
|
+
console.log(`${cpu.cpuName}: ${cpu.temperature.maxCore}°C`);
|
|
109
|
+
|
|
110
|
+
// 一键获取全部系统信息
|
|
111
|
+
const all = await getAllInfo();
|
|
112
|
+
console.log(`OS: ${all.system.os.caption}`);
|
|
113
|
+
console.log(`内存: ${all.memory.usedPercent}%`);
|
|
114
|
+
console.log(`电池: ${all.battery.overallChargePercent}%`);
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## CPU 温度三种模式
|
|
118
|
+
|
|
119
|
+
### 1. 单次模式 — `getCpuTemp()`
|
|
120
|
+
|
|
121
|
+
每次 spawn 新进程,~800ms。偶尔读一次用这个。
|
|
122
|
+
|
|
123
|
+
```js
|
|
124
|
+
const { getCpuTemp } = require('./index');
|
|
125
|
+
const data = await getCpuTemp();
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
返回:`temperature`(每核心/封装/最高温/热区)、`load`、`clock`、`power`、`isCoreTemp`、`cpuName`、`source`。
|
|
129
|
+
|
|
130
|
+
### 2. 常驻模式 — `createCpuTempDaemon()`
|
|
131
|
+
|
|
132
|
+
进程保持运行,每次 ~60ms。自己控制读取节奏用这个。
|
|
133
|
+
|
|
134
|
+
```js
|
|
135
|
+
const { createCpuTempDaemon } = require('./index');
|
|
136
|
+
const daemon = await createCpuTempDaemon();
|
|
137
|
+
const data = await daemon.getTemp(); // ~60ms
|
|
138
|
+
await daemon.close();
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### 3. 监控器模式 — `createCpuTempMonitor()`
|
|
142
|
+
|
|
143
|
+
EventEmitter 事件推送,支持暂停/恢复/动态调间隔。持续监控用这个。
|
|
144
|
+
|
|
145
|
+
```js
|
|
146
|
+
const { createCpuTempMonitor } = require('./index');
|
|
147
|
+
const monitor = await createCpuTempMonitor({ interval: 500 });
|
|
148
|
+
monitor.on('data', data => console.log(`${data.temperature.maxCore}°C`));
|
|
149
|
+
// monitor.setInterval(200); monitor.pause(); monitor.resume();
|
|
150
|
+
await monitor.stop();
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## 系统信息 API(无需管理员)
|
|
154
|
+
|
|
155
|
+
### `getSystemInfo()`
|
|
156
|
+
|
|
157
|
+
操作系统、计算机、BIOS、主板、CPU、开机时间、电源计划。
|
|
158
|
+
|
|
159
|
+
```js
|
|
160
|
+
{
|
|
161
|
+
os: { caption, version, buildNumber, architecture, installDate, lastBootUpTime, uptimeDays, systemDrive },
|
|
162
|
+
computer: { manufacturer, model, name, domain, totalPhysicalMemoryGB, numberOfCores, numberOfLogicalProcessors, systemType },
|
|
163
|
+
bios: { manufacturer, version, releaseDate, serialNumber },
|
|
164
|
+
motherboard: { manufacturer, product, version, serialNumber },
|
|
165
|
+
cpu: { name, manufacturer, numberOfCores, numberOfLogicalProcessors, maxClockSpeedMHz, l2CacheKB, l3CacheKB, socketDesignation, virtualizationEnabled },
|
|
166
|
+
powerPlan: "平衡",
|
|
167
|
+
timezone: "China Standard Time",
|
|
168
|
+
currentTime: "..."
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### `getMemoryInfo()`
|
|
173
|
+
|
|
174
|
+
内存使用情况 + 物理内存条详情。
|
|
175
|
+
|
|
176
|
+
```js
|
|
177
|
+
{
|
|
178
|
+
totalPhysicalGB, usedPhysicalGB, freePhysicalGB, usedPercent,
|
|
179
|
+
totalVirtualGB, freeVirtualGB,
|
|
180
|
+
sticks: [
|
|
181
|
+
{ deviceLocator, bankLabel, capacityGB, speedMHz, configuredSpeedMHz, manufacturer, partNumber, serialNumber, dataWidth }
|
|
182
|
+
],
|
|
183
|
+
stickCount,
|
|
184
|
+
array: { maxCapacityGB, memoryDevices, use }
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
> 注意:部分笔记本(内存焊死)WMI 可能将每个内存颗粒识别为一条,导致 stickCount 偏多。
|
|
189
|
+
|
|
190
|
+
### `getDiskInfo()`
|
|
191
|
+
|
|
192
|
+
物理磁盘 + 逻辑分区 + 实时读写速度。
|
|
193
|
+
|
|
194
|
+
```js
|
|
195
|
+
{
|
|
196
|
+
physicalDisks: [
|
|
197
|
+
{ index, model, manufacturer, interfaceType, mediaType, serialNumber, firmwareRevision, sizeGB, partitions, drives, readBytesPerSec, writeBytesPerSec, percentActive }
|
|
198
|
+
],
|
|
199
|
+
logicalDrives: [
|
|
200
|
+
{ drive, volumeName, fileSystem, sizeGB, usedGB, freeGB, usedPercent, volumeSerialNumber }
|
|
201
|
+
],
|
|
202
|
+
diskCount, totalSizeGB
|
|
203
|
+
}
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### `getNetworkInfo()`
|
|
207
|
+
|
|
208
|
+
网卡列表 + IP 配置 + 实时网速 + WiFi。
|
|
209
|
+
|
|
210
|
+
```js
|
|
211
|
+
{
|
|
212
|
+
adapters: [
|
|
213
|
+
{ name, connectionName, macAddress, adapterType, speedMbps, status, ipAddresses, ipSubnets, defaultIpGateway, dnsServers, dhcpEnabled, bytesReceivedPerSec, bytesSentPerSec, isPhysical }
|
|
214
|
+
],
|
|
215
|
+
activeAdapters: [/* 同上,仅已连接的物理网卡 */],
|
|
216
|
+
adapterCount, activeAdapterCount,
|
|
217
|
+
wifi: { ssId, signalPercent, channel },
|
|
218
|
+
totalDownloadBytesPerSec, totalUploadBytesPerSec
|
|
219
|
+
}
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### `getBatteryInfo()`
|
|
223
|
+
|
|
224
|
+
电池状态 + 健康度 + 电源计划。台式机返回 `hasBattery: false`。
|
|
225
|
+
|
|
226
|
+
```js
|
|
227
|
+
{
|
|
228
|
+
hasBattery: true,
|
|
229
|
+
batteries: [
|
|
230
|
+
{ name, deviceId, status, batteryStatusValue, batteryStatus, chargePercent, estimatedRunTimeMinutes, voltagemV, designCapacitymWh, fullChargeCapacitymWh, healthPercent, cycleCount, manufacturer, chemistry }
|
|
231
|
+
],
|
|
232
|
+
powerPlan: "平衡",
|
|
233
|
+
isCharging: false,
|
|
234
|
+
overallChargePercent: 99
|
|
235
|
+
}
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
> 部分笔记本 WMI 不暴露设计容量/循环次数,对应字段为 null。
|
|
239
|
+
|
|
240
|
+
### `getGpuInfo()`
|
|
241
|
+
|
|
242
|
+
显卡 + 显示器信息。
|
|
243
|
+
|
|
244
|
+
```js
|
|
245
|
+
{
|
|
246
|
+
gpus: [
|
|
247
|
+
{ name, isVirtual, displayMode, adapterCompatibility, adapterRAMMB, driverVersion, driverDate, videoProcessor, currentHorizontalResolution, currentVerticalResolution, currentRefreshRate, currentBitsPerPixel }
|
|
248
|
+
],
|
|
249
|
+
monitors: [
|
|
250
|
+
{ name, monitorManufacturer, monitorType, screenHeight, screenWidth }
|
|
251
|
+
],
|
|
252
|
+
gpuCount, monitorCount, primaryResolution
|
|
253
|
+
}
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### `getUsbInfo()`
|
|
257
|
+
|
|
258
|
+
USB 控制器 + 已连接设备。
|
|
259
|
+
|
|
260
|
+
```js
|
|
261
|
+
{
|
|
262
|
+
controllers: [{ name, manufacturer, status, deviceId }],
|
|
263
|
+
controllerCount,
|
|
264
|
+
devices: [{ name, description, manufacturer, status, service, pnpDeviceId, classGuid }],
|
|
265
|
+
deviceCount
|
|
266
|
+
}
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### `getProcesses(options?)`
|
|
270
|
+
|
|
271
|
+
进程列表,支持排序、Top N、实时 CPU%、按名称聚合。
|
|
272
|
+
|
|
273
|
+
```js
|
|
274
|
+
const procs = await getProcesses({
|
|
275
|
+
top: 10,
|
|
276
|
+
sortBy: 'cpu', // 'memory' / 'cpu' / 'name'
|
|
277
|
+
includeCpu: true, // 实时 CPU%,默认 false,常驻采样器自动启停
|
|
278
|
+
groupByName: true, // 按名称聚合,默认 false
|
|
279
|
+
includeInstallTime: true, // 安装时间,默认 false
|
|
280
|
+
backend: 'koffi' // 'koffi'(默认,~28ms)/ 'wmi'(~115ms)
|
|
281
|
+
});
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
**koffi 后端返回**:
|
|
285
|
+
|
|
286
|
+
```js
|
|
287
|
+
{
|
|
288
|
+
total, returned, backend,
|
|
289
|
+
processes: [
|
|
290
|
+
{
|
|
291
|
+
pid, name, parentPid, threads,
|
|
292
|
+
memoryMB, memoryPrivateMB,
|
|
293
|
+
cpuPercent, // 实时 CPU%(需 includeCpu=true)
|
|
294
|
+
exePath,
|
|
295
|
+
installTime, // 需 includeInstallTime=true
|
|
296
|
+
// groupByName=true 时额外返回:
|
|
297
|
+
pids: [], // 组内所有 PID
|
|
298
|
+
instances: [], // 组内实例明细
|
|
299
|
+
percent // 占总内存百分比
|
|
300
|
+
}
|
|
301
|
+
]
|
|
302
|
+
}
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
**高频优化**:`includeCpu=true` 时启动 1s 常驻采样器,自动维护 CPU% 基线,空闲 15s 自动停止。后续 `getProcesses` 读缓存毫秒级返回。
|
|
306
|
+
|
|
307
|
+
### `getServicesInfo(options?)`
|
|
308
|
+
|
|
309
|
+
Windows 服务列表。
|
|
310
|
+
|
|
311
|
+
```js
|
|
312
|
+
const services = await getServicesInfo({ runningOnly: false });
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
```js
|
|
316
|
+
{
|
|
317
|
+
total, running, stopped,
|
|
318
|
+
services: [
|
|
319
|
+
{ name, displayName, state, status, startMode, startName, pathName, description, processId, acceptStop, acceptPause, serviceType }
|
|
320
|
+
]
|
|
321
|
+
}
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
### `getAllHardwareInfo()`
|
|
325
|
+
|
|
326
|
+
OpenHardwareMonitor 全硬件传感器(CPU/主板/内存/硬盘/GPU 的温度、电压、频率、负载、风扇等)。**需管理员**。
|
|
327
|
+
|
|
328
|
+
## 一键汇总
|
|
329
|
+
|
|
330
|
+
### `getAllInfo(options?)`
|
|
331
|
+
|
|
332
|
+
并行获取全部信息,单个模块失败不影响其他。
|
|
333
|
+
|
|
334
|
+
```js
|
|
335
|
+
const all = await getAllInfo({
|
|
336
|
+
includeProcesses: true, // 是否包含进程列表,默认 false
|
|
337
|
+
includeServices: true, // 是否包含服务列表,默认 false
|
|
338
|
+
includeOhmHardware: false, // 是否包含 OHM 全硬件传感器(需管理员),默认 false
|
|
339
|
+
processTop: 20 // 进程前 N 个,默认 20
|
|
340
|
+
});
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
返回字段:`system`、`cpu`、`memory`、`disk`、`network`、`battery`、`gpu`、`usb`,可选 `processes`、`services`、`ohmHardware`,以及 `timestamp` 和 `errors`(失败模块的错误信息)。
|
|
344
|
+
|
|
345
|
+
```js
|
|
346
|
+
console.log(all.system.os.caption); // Windows 10 专业版
|
|
347
|
+
console.log(all.cpu.temperature.maxCore); // 72
|
|
348
|
+
console.log(all.memory.usedPercent); // 69.09
|
|
349
|
+
console.log(all.battery.overallChargePercent); // 99
|
|
350
|
+
console.log(all.errors); // { battery: "..." } 或 null
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
## 完整 API 列表
|
|
354
|
+
|
|
355
|
+
| API | 说明 | 需管理员 |
|
|
356
|
+
|---|---|---|
|
|
357
|
+
| `getCpuTemp()` | CPU 温度/负载/频率/功耗(多层降级) | 真实温度需要 |
|
|
358
|
+
| `getAllHardwareInfo()` | OHM 全硬件传感器 | 是 |
|
|
359
|
+
| `createCpuTempDaemon()` | CPU 温度常驻进程 | 是 |
|
|
360
|
+
| `createCpuTempMonitor()` | CPU 温度高频监控器 | 是 |
|
|
361
|
+
| `getSystemInfo()` | 系统/OS/BIOS/主板/CPU | 否 |
|
|
362
|
+
| `getMemoryInfo()` | 内存详情/内存条 | 否 |
|
|
363
|
+
| `getDiskInfo()` | 硬盘/分区/读写速度 | 否 |
|
|
364
|
+
| `getNetworkInfo()` | 网卡/IP/网速/WiFi | 否 |
|
|
365
|
+
| `getBatteryInfo()` | 电池/健康度/电源计划 | 否 |
|
|
366
|
+
| `getGpuInfo()` | 显卡/显示器 | 否 |
|
|
367
|
+
| `getUsbInfo()` | USB 控制器/设备 | 否 |
|
|
368
|
+
| `getProcesses()` | 进程列表(koffi 直调 Win32 API,~28ms,支持 CPU%/按名称聚合/安装时间) | 否 |
|
|
369
|
+
| `getServicesInfo()` | 服务列表 | 否 |
|
|
370
|
+
| `getPublicIp()` | 公网 IP(DNS 查询为主,HTTPS 兜底,60 秒缓存) | 否 |
|
|
371
|
+
| `getBackendUsage()` | 后端资源占用(Node.js + 子进程,同步 ~5-10ms) | 否 |
|
|
372
|
+
| `getAllInfo()` | 一键汇总全部 | 部分需要 |
|
|
373
|
+
| `createSysInfoDaemon()` | 统一常驻进程(所有模块复用一个 PowerShell 进程) | 否 |
|
|
374
|
+
| `createHardwareService()` | **统一常驻服务**(整合所有模块,一个入口调用) | 否 |
|
|
375
|
+
| `killProcess()` | 结束进程(fkill,支持 PID/端口/名称/混合数组,含子进程树) | 否 |
|
|
376
|
+
| `findPidsByPort(port, protocol?)` | 按端口号查找占用 PID(netstat 解析) | 否 |
|
|
377
|
+
| `findPidsByName(name)` | 按进程名查找 PID(koffi 匹配,不区分大小写) | 否 |
|
|
378
|
+
| `showItemInFolder()` | 在资源管理器中定位到文件 | 否 |
|
|
379
|
+
| `createDiskWatcher()` | 磁盘插拔监听(WMI 事件 + 5s 轮询兜底,EventEmitter) | 否 |
|
|
380
|
+
| `listDriveLetters()` | 列出当前所有盘符 | 否 |
|
|
381
|
+
| `getProcessIcon()` / `getProcessIcons()` | 提取 exe 关联图标(base64 PNG,批量提取,按需) | 否 |
|
|
382
|
+
|
|
383
|
+
## 统一常驻服务(推荐)
|
|
384
|
+
|
|
385
|
+
一个入口整合所有常驻模块,无需分别创建和管理 SysInfoDaemon / CpuTempMonitor / 进程采样器 / 磁盘监听器。
|
|
386
|
+
|
|
387
|
+
```js
|
|
388
|
+
const { createHardwareService } = require('hardware-info');
|
|
389
|
+
|
|
390
|
+
// 创建即启动(CPU 温度异步初始化,不阻塞)
|
|
391
|
+
const service = await createHardwareService({
|
|
392
|
+
cpuTempInterval: 1000, // CPU 温度采样间隔 ms,0=不自动采样
|
|
393
|
+
diskWatchInterval: 2000, // 磁盘插拔监听间隔 ms
|
|
394
|
+
systemCacheTtl: 30000, // system 缓存 TTL ms
|
|
395
|
+
networkCacheTtl: 30000, // 网卡配置缓存 TTL ms
|
|
396
|
+
enableCpuTemp: true, // 是否启用 CPU 温度,默认 true
|
|
397
|
+
enableDiskWatcher: true // 是否启用磁盘监听,默认 true
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
// 系统信息(代理到 SysInfoDaemon,高频低延迟)
|
|
401
|
+
const mem = await service.getMemory();
|
|
402
|
+
const net = await service.getNetwork();
|
|
403
|
+
const sys = await service.getSystem();
|
|
404
|
+
|
|
405
|
+
// 进程(自动带 CPU%,采样器自动启停,无需手动管理)
|
|
406
|
+
const topCpu = await service.getProcesses({ top: 10, sortBy: 'cpu' });
|
|
407
|
+
|
|
408
|
+
// CPU 温度(自动采样,同步返回最新值,无需 await)
|
|
409
|
+
const temp = service.getCpuTemp();
|
|
410
|
+
|
|
411
|
+
// 公网 IP(带 60s 缓存)
|
|
412
|
+
const ip = await service.getPublicIp();
|
|
413
|
+
|
|
414
|
+
// 后端资源占用(同步)
|
|
415
|
+
const usage = service.getBackendUsage();
|
|
416
|
+
|
|
417
|
+
// 进程操作
|
|
418
|
+
await service.killProcess(1234); // 按 PID
|
|
419
|
+
await service.killProcess({ port: 3000 }); // 按端口
|
|
420
|
+
await service.killProcess({ name: 'chrome' }); // 按名称
|
|
421
|
+
const pids = await service.findPidsByPort(3000);
|
|
422
|
+
const pids2 = service.findPidsByName('chrome');
|
|
423
|
+
|
|
424
|
+
// 事件
|
|
425
|
+
service.on('cpu-temp', (data) => console.log(data.temperature.maxCore + '°C'));
|
|
426
|
+
service.on('disk-change', ({ added, removed }) => console.log('磁盘变化', added, removed));
|
|
427
|
+
|
|
428
|
+
// 暂停/恢复/关闭
|
|
429
|
+
service.pause(); // 暂停所有采样
|
|
430
|
+
service.resume(); // 恢复
|
|
431
|
+
await service.close(); // 关闭所有子模块,释放资源
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
### 统一服务 API 一览
|
|
435
|
+
|
|
436
|
+
| 类别 | 方法/事件 | 说明 |
|
|
437
|
+
|---|---|---|
|
|
438
|
+
| **系统信息** | `getSystem()` `getMemory()` `getDisk()` `getNetwork()` `getBattery()` `getGpu()` `getUsb()` `getServices()` `getAll()` | 代理到 SysInfoDaemon |
|
|
439
|
+
| **进程** | `getProcesses({top, sortBy, groupByName})` | 默认 `includeCpu=true`,自动管理采样器 |
|
|
440
|
+
| **CPU 温度** | `getCpuTemp()` | 同步返回最新采样值(自动采样模式) |
|
|
441
|
+
| | `fetchCpuTemp()` | 手动拉取一次(`cpuTempInterval=0` 时用) |
|
|
442
|
+
| **公网 IP** | `getPublicIp()` | 带 60s 缓存 |
|
|
443
|
+
| **磁盘** | `getDisks()` | 当前所有盘符 |
|
|
444
|
+
| **后端资源** | `getBackendUsage()` | Node.js + 子进程内存/CPU/线程 |
|
|
445
|
+
| **进程操作** | `killProcess(input)` | PID/端口/名称/混合数组 |
|
|
446
|
+
| | `findPidsByPort(port, protocol?)` | 按端口查 PID |
|
|
447
|
+
| | `findPidsByName(name)` | 按名称查 PID |
|
|
448
|
+
| | `showItemInFolder(path)` | 资源管理器定位文件 |
|
|
449
|
+
| **事件** | `on('cpu-temp', cb)` `on('disk-change', cb)` `on('error', cb)` `on('close', cb)` `on('pause', cb)` `on('resume', cb)` | |
|
|
450
|
+
| **控制** | `pause()` `resume()` `close()` `getStatus()` | |
|
|
451
|
+
|
|
452
|
+
## 常驻进程模式(SysInfoDaemon)
|
|
453
|
+
|
|
454
|
+
所有模块复用一个 PowerShell 常驻进程,通过 stdin/stdout 通信,避免每次 spawn 新进程的 ~1500ms 启动开销。内存占用 ~50MB。
|
|
455
|
+
|
|
456
|
+
```js
|
|
457
|
+
const { createSysInfoDaemon } = require('hardware-info');
|
|
458
|
+
|
|
459
|
+
const daemon = await createSysInfoDaemon();
|
|
460
|
+
|
|
461
|
+
const mem = await daemon.getMemory(); // ~85ms
|
|
462
|
+
const net = await daemon.getNetwork(); // ~270ms(含实时网速)
|
|
463
|
+
const procs = await daemon.getProcesses({ top: 10 }); // ~115ms
|
|
464
|
+
const sys = await daemon.getSystem(); // 缓存命中 ~1ms
|
|
465
|
+
|
|
466
|
+
await daemon.close();
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
### 可配置缓存 TTL
|
|
470
|
+
|
|
471
|
+
```js
|
|
472
|
+
const daemon = await createSysInfoDaemon({
|
|
473
|
+
systemCacheTtl: 10000, // system 缓存 10 秒(默认 30000ms)
|
|
474
|
+
networkCacheTtl: 30000, // network 网卡配置缓存 30 秒(默认 30000ms)
|
|
475
|
+
maxRestarts: 5, // 进程意外退出最大重启次数(默认 3)
|
|
476
|
+
verbose: false // 是否输出 stderr 调试信息
|
|
477
|
+
});
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
> 设为 `0` 可禁用对应缓存(每次都实时查询)。网速、内存、进程等动态数据不受缓存影响,始终实时。
|
|
481
|
+
|
|
482
|
+
### 各模块查询延迟(常驻模式,i5-11300H 实测)
|
|
483
|
+
|
|
484
|
+
| 模块 | 延迟 | 说明 |
|
|
485
|
+
|---|---|---|
|
|
486
|
+
| `getSystem()` | 首次 ~1200ms / 缓存命中 **1ms** | 30 秒 TTL 缓存 |
|
|
487
|
+
| `getMemory()` | ~85ms | 实时 |
|
|
488
|
+
| `getDisk()` | ~356ms | 实时 |
|
|
489
|
+
| `getNetwork()` | ~270ms | 网卡配置 30 秒缓存,网速实时 |
|
|
490
|
+
| `getBattery()` | ~25ms | 实时 |
|
|
491
|
+
| `getGpu()` | ~43ms | 实时 |
|
|
492
|
+
| `getUsb()` | ~177ms | 实时 |
|
|
493
|
+
| `getProcesses()` | ~115ms | 实时 |
|
|
494
|
+
| `getServices()` | ~332ms | 实时 |
|
|
495
|
+
|
|
496
|
+
### 缓存策略(重要)
|
|
497
|
+
|
|
498
|
+
常驻进程为降低高频调用延迟,对**变化不频繁**的数据做了缓存,其余数据每次实时查询:
|
|
499
|
+
|
|
500
|
+
#### 有缓存的数据
|
|
501
|
+
|
|
502
|
+
| 模块 | 缓存字段 | TTL | 说明 |
|
|
503
|
+
|---|---|---|---|
|
|
504
|
+
| `getSystem()` | `os`、`computer`、`bios`、`motherboard`、`cpu`、`powerPlan`、`timezone` | **30 秒** | 电源计划可能切换,30 秒内会刷新;OS/CPU/BIOS 等极少变化 |
|
|
505
|
+
| `getNetwork()` | 网卡 `name`、`macAddress`、`ipAddresses`、`speedMbps`、`status`、`dnsServers` | **30 秒** | IP/网卡配置变化不频繁;**网速每次实时查询** |
|
|
506
|
+
|
|
507
|
+
#### 每次实时查询(无缓存)
|
|
508
|
+
|
|
509
|
+
- 内存使用率、已用/可用内存
|
|
510
|
+
- 硬盘使用率、实时读写速度
|
|
511
|
+
- 电池电量、充电状态、健康度
|
|
512
|
+
- 显卡当前分辨率/刷新率
|
|
513
|
+
- USB 设备列表
|
|
514
|
+
- 进程列表(CPU/内存占用)
|
|
515
|
+
- 服务列表
|
|
516
|
+
- 网络上下行网速、包速率
|
|
517
|
+
- CPU 温度(独立 OHM 常驻进程,每次读 MSR 寄存器)
|
|
518
|
+
- `getSystem()` 返回中的 `uptimeSeconds`、`uptimeDays`、`currentTime`(每次更新)
|
|
519
|
+
|
|
520
|
+
#### `os` 字段说明
|
|
521
|
+
|
|
522
|
+
`getSystem()` 返回的 `os` 对象包含:
|
|
523
|
+
|
|
524
|
+
| 字段 | 说明 | 示例 |
|
|
525
|
+
|---|---|---|
|
|
526
|
+
| `caption` | 操作系统名称 | `Microsoft Windows 10 专业版` |
|
|
527
|
+
| `version` | 版本号 | `10.0.19045` |
|
|
528
|
+
| `buildNumber` | 构建号 | `19045` |
|
|
529
|
+
| `architecture` | 系统架构 | `64 位` |
|
|
530
|
+
| `installDate` | 安装日期(ISO 格式) | `2021-07-22T...` |
|
|
531
|
+
| `lastBootUpTime` | 上次启动时间(ISO 格式) | `2026-09-05T...` |
|
|
532
|
+
| `systemDrive` | 系统盘 | `C:` |
|
|
533
|
+
|
|
534
|
+
## API 返回字段详解
|
|
535
|
+
|
|
536
|
+
### CPU 温度 `getCpuTemp()`
|
|
537
|
+
|
|
538
|
+
| 字段 | 说明 | 示例值 |
|
|
539
|
+
|---|---|---|
|
|
540
|
+
| `source` | 数据来源 | `openhardwaremonitor` / `performance_counter` |
|
|
541
|
+
| `isCoreTemp` | 是否真实核心温度 | `true` / `false` |
|
|
542
|
+
| `cpuName` | CPU 型号 | `11th Gen Intel Core i5-11300H` |
|
|
543
|
+
| `temperature.cores[]` | 每核心温度 | `[{name:"CPU Core #1", value:57}]` |
|
|
544
|
+
| `temperature.package` | 封装温度 | `65` |
|
|
545
|
+
| `temperature.maxCore` | 最高核心温度 | `65` |
|
|
546
|
+
| `temperature.zones[]` | ACPI 热区(降级时) | `[{zone:"\\_TZ.TZ00", celsius:27.85}]` |
|
|
547
|
+
| `load[]` | 每核心负载 + CPU Total | `[{name:"CPU Total", value:18.75}]` % |
|
|
548
|
+
| `clock[]` | 每核心频率 + Bus Speed | `[{name:"CPU Core #1", value:4013.75}]` MHz |
|
|
549
|
+
| `power[]` | 功耗(Package/Cores/Graphics/DRAM) | `[{name:"CPU Package", value:8.98}]` W |
|
|
550
|
+
| `note` | 说明文字 | |
|
|
551
|
+
| `errors[]` | 各层降级错误 | |
|
|
552
|
+
|
|
553
|
+
### 系统信息 `getSystemInfo()`
|
|
554
|
+
|
|
555
|
+
| 字段 | 说明 |
|
|
556
|
+
|---|---|
|
|
557
|
+
| `os.caption` / `version` / `buildNumber` | 系统名称 / 版本号 / 构建号 |
|
|
558
|
+
| `os.architecture` / `installDate` / `lastBootUpTime` / `systemDrive` | 架构 / 安装日期 / 上次启动 / 系统盘 |
|
|
559
|
+
| `computer.manufacturer` / `model` / `name` / `domain` | 厂商 / 型号 / 计算机名 / 域 |
|
|
560
|
+
| `computer.totalPhysicalMemoryGB` / `numberOfLogicalProcessors` / `systemType` | 总内存 / 逻辑处理器数 / 系统类型 |
|
|
561
|
+
| `bios.manufacturer` / `version` / `releaseDate` / `serialNumber` | BIOS 厂商 / 版本 / 发布日期 / 序列号 |
|
|
562
|
+
| `motherboard.manufacturer` / `product` / `version` / `serialNumber` | 主板厂商 / 型号 / 版本 / 序列号 |
|
|
563
|
+
| `cpu.name` / `manufacturer` | CPU 名称 / 厂商 |
|
|
564
|
+
| `cpu.numberOfCores` / `numberOfLogicalProcessors` | 核心数 / 线程数 |
|
|
565
|
+
| `cpu.maxClockSpeedMHz` / `l2CacheKB` / `l3CacheKB` | 最大频率 / L2缓存 / L3缓存 |
|
|
566
|
+
| `cpu.socketDesignation` / `virtualizationEnabled` | 插槽 / 虚拟化是否开启 |
|
|
567
|
+
| `powerPlan` / `timezone` | 电源计划 / 时区 |
|
|
568
|
+
| `uptimeSeconds` / `uptimeDays` / `currentTime` | 开机时长(秒/天)/ 当前时间 |
|
|
569
|
+
|
|
570
|
+
### 内存 `getMemoryInfo()`
|
|
571
|
+
|
|
572
|
+
| 字段 | 说明 |
|
|
573
|
+
|---|---|
|
|
574
|
+
| `totalPhysicalGB` / `usedPhysicalGB` / `freePhysicalGB` / `usedPercent` | 总内存 / 已用 / 可用 / 使用率 |
|
|
575
|
+
| `totalVirtualGB` / `freeVirtualGB` | 虚拟内存总量 / 可用 |
|
|
576
|
+
| `sticks[].deviceLocator` / `bankLabel` | 插槽位置 / 通道标签 |
|
|
577
|
+
| `sticks[].capacityGB` / `speedMHz` / `configuredSpeedMHz` | 容量 / 标称频率 / 实际频率 |
|
|
578
|
+
| `sticks[].manufacturer` / `partNumber` / `serialNumber` / `dataWidth` | 厂商 / 型号 / 序列号 / 位宽 |
|
|
579
|
+
| `stickCount` | 内存条数 |
|
|
580
|
+
| `array.maxCapacityGB` / `array.memoryDevices` | 最大支持容量 / 最大插槽数 |
|
|
581
|
+
|
|
582
|
+
### 硬盘 `getDiskInfo()`
|
|
583
|
+
|
|
584
|
+
| 字段 | 说明 |
|
|
585
|
+
|---|---|
|
|
586
|
+
| `physicalDisks[].index` / `model` / `interfaceType` / `mediaType` | 索引 / 型号 / 接口类型 / 介质类型 |
|
|
587
|
+
| `physicalDisks[].serialNumber` / `firmwareRevision` / `sizeGB` | 序列号 / 固件版本 / 容量 |
|
|
588
|
+
| `physicalDisks[].drives` | 关联盘符数组,如 `['C:', 'D:']` |
|
|
589
|
+
| `physicalDisks[].readBytesPerSec` / `writeBytesPerSec` / `percentActive` | 实时读速 / 写速 / 活跃时间% |
|
|
590
|
+
| `logicalDrives[].drive` / `volumeName` / `fileSystem` | 盘符 / 卷标 / 文件系统 |
|
|
591
|
+
| `logicalDrives[].sizeGB` / `usedGB` / `freeGB` / `usedPercent` | 总量 / 已用 / 可用 / 使用率 |
|
|
592
|
+
| `diskCount` / `totalSizeGB` | 物理磁盘数 / 总容量 |
|
|
593
|
+
|
|
594
|
+
### 网络 `getNetworkInfo()`
|
|
595
|
+
|
|
596
|
+
| 字段 | 说明 |
|
|
597
|
+
|---|---|
|
|
598
|
+
| `adapters[]` / `activeAdapters[]` | 所有网卡 / 活跃网卡(已连接的物理网卡) |
|
|
599
|
+
| `adapters[].name` / `connectionName` / `macAddress` | 名称 / 连接名 / MAC |
|
|
600
|
+
| `adapters[].speedMbps` / `status` / `isPhysical` | 速率Mbps / 连接状态(2=已连接) / 是否物理 |
|
|
601
|
+
| `adapters[].ipAddresses[]` / `defaultIpGateway[]` / `dnsServers[]` | IP / 网关 / DNS |
|
|
602
|
+
| `adapters[].bytesReceivedPerSec` / `bytesSentPerSec` | **实时下载 / 上传速度** B/s |
|
|
603
|
+
| `adapters[].packetsReceivedPerSec` / `packetsSentPerSec` | 收包 / 发包速率 |
|
|
604
|
+
| `adapterCount` / `activeAdapterCount` | 总数 / 活跃数 |
|
|
605
|
+
| `wifi.ssId` / `wifi.signalPercent` | WiFi名称 / 信号强度% |
|
|
606
|
+
| `totalDownloadBytesPerSec` / `totalUploadBytesPerSec` | 总下载 / 总上传速度 |
|
|
607
|
+
|
|
608
|
+
### 电池 `getBatteryInfo()`
|
|
609
|
+
|
|
610
|
+
| 字段 | 说明 |
|
|
611
|
+
|---|---|
|
|
612
|
+
| `hasBattery` | 是否有电池 |
|
|
613
|
+
| `batteries[].name` / `deviceId` / `status` | 名称 / 设备ID / 状态 |
|
|
614
|
+
| `batteries[].batteryStatusValue` / `batteryStatus` | 状态值 / 状态文字 |
|
|
615
|
+
| `batteries[].chargePercent` / `estimatedRunTimeMinutes` | 电量% / 预计续航分钟 |
|
|
616
|
+
| `batteries[].voltagemV` | 电压 mV |
|
|
617
|
+
| `batteries[].designCapacitymWh` / `fullChargeCapacitymWh` | 设计容量 / 满充容量 mWh |
|
|
618
|
+
| `batteries[].healthPercent` / `cycleCount` | 健康度% / 循环次数 |
|
|
619
|
+
| `batteries[].manufacturer` / `chemistry` | 厂商 / 化学类型 |
|
|
620
|
+
| `isCharging` / `overallChargePercent` | 是否充电中 / 总电量% |
|
|
621
|
+
|
|
622
|
+
### 显卡/显示器 `getGpuInfo()`
|
|
623
|
+
|
|
624
|
+
| 字段 | 说明 |
|
|
625
|
+
|---|---|
|
|
626
|
+
| `gpus[].name` / `isVirtual` / `displayMode` | 名称 / 是否虚拟 / 显示模式(已格式化) |
|
|
627
|
+
| `gpus[].adapterCompatibility` / `adapterRAMMB` | 兼容厂商 / 显存MB |
|
|
628
|
+
| `gpus[].driverVersion` / `driverDate` / `videoProcessor` | 驱动版本 / 驱动日期 / 视频处理器 |
|
|
629
|
+
| `gpus[].currentHorizontalResolution` / `currentVerticalResolution` | 当前水平 / 垂直分辨率 |
|
|
630
|
+
| `gpus[].currentRefreshRate` / `currentBitsPerPixel` | 当前刷新率 / 色深 |
|
|
631
|
+
| `monitors[].name` / `monitorManufacturer` / `monitorType` | 名称 / 厂商 / 类型 |
|
|
632
|
+
| `monitors[].screenWidth` / `screenHeight` | 宽 / 高 |
|
|
633
|
+
| `gpuCount` / `monitorCount` / `primaryResolution` | 显卡数 / 显示器数 / 主分辨率 |
|
|
634
|
+
|
|
635
|
+
### USB `getUsbInfo()`
|
|
636
|
+
|
|
637
|
+
| 字段 | 说明 |
|
|
638
|
+
|---|---|
|
|
639
|
+
| `controllers[].name` / `manufacturer` / `status` | 控制器名称 / 厂商 / 状态 |
|
|
640
|
+
| `controllerCount` | 控制器数 |
|
|
641
|
+
| `devices[].name` / `description` / `manufacturer` | 设备名称 / 描述 / 厂商 |
|
|
642
|
+
| `devices[].status` / `service` | 状态 / 服务 |
|
|
643
|
+
| `deviceCount` | 设备数 |
|
|
644
|
+
|
|
645
|
+
### 进程 `getProcesses({top, sortBy, backend, includeCpu, groupByName, includeInstallTime})`
|
|
646
|
+
|
|
647
|
+
**双后端**:
|
|
648
|
+
- `koffi`(默认):直调 Win32 API(Toolhelp32+psapi+GetProcessTimes),335进程 ~28ms,支持实时 CPU%
|
|
649
|
+
- `wmi`:PowerShell Get-Process,~115ms,命令行信息更全
|
|
650
|
+
|
|
651
|
+
**koffi 后端字段**:
|
|
652
|
+
|
|
653
|
+
| 字段 | 说明 |
|
|
654
|
+
|---|---|
|
|
655
|
+
| `total` / `returned` / `backend` | 总进程数 / 返回数量 / 后端类型 |
|
|
656
|
+
| `processes[].pid` / `name` | PID / 进程名(已去 .exe) |
|
|
657
|
+
| `processes[].parentPid` | 父进程 PID |
|
|
658
|
+
| `processes[].threads` | 线程数 |
|
|
659
|
+
| `processes[].memoryMB` / `memoryPrivateMB` | 工作集内存 / 私有内存 MB |
|
|
660
|
+
| `processes[].cpuPercent` | 实时 CPU%(需 includeCpu=true,第一次为0,后续正常) |
|
|
661
|
+
| `processes[].exePath` | exe 完整路径 |
|
|
662
|
+
| `processes[].installTime` | 安装时间(需 includeInstallTime=true,YYYY-MM-DD) |
|
|
663
|
+
| `processes[].pids[]` / `instances[]` | 聚合后:所有PID / 组内实例明细(需 groupByName=true) |
|
|
664
|
+
| `processes[].percent` | 聚合后:占总内存百分比 |
|
|
665
|
+
|
|
666
|
+
**高频优化**:includeCpu=true 时启动 1s 常驻采样器,自动维护 CPU% 基线,空闲 15s 自动停止。getProcesses 读缓存毫秒级返回。
|
|
667
|
+
|
|
668
|
+
### 进程操作
|
|
669
|
+
|
|
670
|
+
#### `killProcess(input)`
|
|
671
|
+
|
|
672
|
+
结束进程(使用 fkill,支持 PID/端口号/进程名/混合数组,含子进程树)。自动拒绝结束当前进程自身和父进程。
|
|
673
|
+
|
|
674
|
+
```js
|
|
675
|
+
const { killProcess } = require('hardware-info');
|
|
676
|
+
|
|
677
|
+
// 按 PID
|
|
678
|
+
const result = await killProcess(1234);
|
|
679
|
+
// 批量 PID
|
|
680
|
+
await killProcess([1234, 5678]);
|
|
681
|
+
|
|
682
|
+
// 按端口号
|
|
683
|
+
await killProcess({ port: 3000 });
|
|
684
|
+
await killProcess({ port: 3000, protocol: 'tcp' }); // 'tcp'/'udp'/'all'(默认)
|
|
685
|
+
|
|
686
|
+
// 按进程名
|
|
687
|
+
await killProcess({ name: 'chrome' });
|
|
688
|
+
await killProcess({ name: ['chrome', 'firefox'] });
|
|
689
|
+
|
|
690
|
+
// 混合数组
|
|
691
|
+
await killProcess([1234, { port: 3000 }, { name: 'chrome' }]);
|
|
692
|
+
```
|
|
693
|
+
|
|
694
|
+
返回 `{ ok, killed, failed, message? }`。
|
|
695
|
+
|
|
696
|
+
#### `findPidsByPort(port, protocol?)`
|
|
697
|
+
|
|
698
|
+
查找占用指定端口的进程 PID(netstat -ano 解析,零依赖)。
|
|
699
|
+
|
|
700
|
+
```js
|
|
701
|
+
const pids = await findPidsByPort(3000); // 所有协议
|
|
702
|
+
const pids = await findPidsByPort(3000, 'tcp'); // 仅 TCP
|
|
703
|
+
// 返回: [1234, 5678]
|
|
704
|
+
```
|
|
705
|
+
|
|
706
|
+
#### `findPidsByName(name)`
|
|
707
|
+
|
|
708
|
+
按进程名查找 PID(koffi 进程枚举匹配,不区分大小写,自动忽略 .exe)。
|
|
709
|
+
|
|
710
|
+
```js
|
|
711
|
+
const pids = findPidsByName('chrome');
|
|
712
|
+
// 返回: [1234, 5678]
|
|
713
|
+
```
|
|
714
|
+
|
|
715
|
+
#### `showItemInFolder(filePath)`
|
|
716
|
+
|
|
717
|
+
在资源管理器中打开并定位到文件(`explorer /select,<path>`)。
|
|
718
|
+
|
|
719
|
+
```js
|
|
720
|
+
const { ok, message } = showItemInFolder('C:\\path\\to\\app.exe');
|
|
721
|
+
```
|
|
722
|
+
|
|
723
|
+
### 磁盘插拔监听 `createDiskWatcher({interval})`
|
|
724
|
+
|
|
725
|
+
WMI 事件监听(Win32_VolumeChangeEvent,插拔瞬间触发)+ 5s 低频轮询兜底。EventEmitter,不占用大量 CPU。
|
|
726
|
+
|
|
727
|
+
```js
|
|
728
|
+
const { createDiskWatcher } = require('hardware-info');
|
|
729
|
+
|
|
730
|
+
const watcher = createDiskWatcher({ interval: 5000 });
|
|
731
|
+
watcher.on('change', ({ added, removed, disks }) => {
|
|
732
|
+
console.log('新增盘符:', added); // ['E']
|
|
733
|
+
console.log('移除盘符:', removed); // ['E']
|
|
734
|
+
console.log('当前所有:', disks); // ['C','D']
|
|
735
|
+
});
|
|
736
|
+
watcher.start();
|
|
737
|
+
// ...
|
|
738
|
+
watcher.stop();
|
|
739
|
+
```
|
|
740
|
+
|
|
741
|
+
方法:`start()` / `stop()` / `getDisks()`。
|
|
742
|
+
|
|
743
|
+
### 进程图标 `getProcessIcon(exePath)` / `getProcessIcons(paths)`
|
|
744
|
+
|
|
745
|
+
提取 exe 关联图标,输出 base64 PNG。用 PowerShell System.Drawing,按需调用(图标是静态属性,建议调用方缓存),不进高频路径。
|
|
746
|
+
|
|
747
|
+
```js
|
|
748
|
+
// 单个
|
|
749
|
+
const iconBase64 = await getProcessIcon('C:\\path\\to\\app.exe');
|
|
750
|
+
|
|
751
|
+
// 批量(路径走 stdin,无命令行长度限制)
|
|
752
|
+
const icons = await getProcessIcons(['C:\\a.exe', 'C:\\b.exe']);
|
|
753
|
+
// icons = { 'C:\\a.exe': 'base64...', 'C:\\b.exe': 'base64...' }
|
|
754
|
+
```
|
|
755
|
+
|
|
756
|
+
### 后端资源占用 `getBackendUsage()`
|
|
757
|
+
|
|
758
|
+
获取当前 Node.js 进程 + 所有子进程的内存/CPU/线程占用。同步 ~5-10ms,高频安全。
|
|
759
|
+
|
|
760
|
+
```js
|
|
761
|
+
const usage = getBackendUsage();
|
|
762
|
+
// {
|
|
763
|
+
// node: { pid, memory: { workingSetMB, heapUsedMB, heapTotalMB }, cpuPercent, threads },
|
|
764
|
+
// children: [ { pid, name, memoryMB, cpuPercent, threads } ],
|
|
765
|
+
// total: { processCount, memoryMB, cpuPercent, threads }
|
|
766
|
+
// }
|
|
767
|
+
```
|
|
768
|
+
|
|
769
|
+
### 公网 IP `getPublicIp()`
|
|
770
|
+
|
|
771
|
+
DNS 查询为主(OpenDNS myip.opendns.com,~45ms)→ Google DNS → HTTPS 三源兜底,60 秒缓存,零依赖。
|
|
772
|
+
|
|
773
|
+
```js
|
|
774
|
+
const ip = await getPublicIp();
|
|
775
|
+
// "112.2.231.35"
|
|
776
|
+
```
|
|
777
|
+
|
|
778
|
+
### 服务 `getServicesInfo({runningOnly})`
|
|
779
|
+
|
|
780
|
+
| 字段 | 说明 |
|
|
781
|
+
|---|---|
|
|
782
|
+
| `total` / `running` / `stopped` | 总数 / 运行中 / 已停止 |
|
|
783
|
+
| `services[].name` / `displayName` | 服务名 / 显示名 |
|
|
784
|
+
| `services[].state` / `status` / `startMode` | 状态 / 状态2 / 启动类型 |
|
|
785
|
+
| `services[].startName` / `pathName` / `description` | 运行账户 / 路径 / 描述 |
|
|
786
|
+
| `services[].processId` / `acceptStop` / `serviceType` | 关联PID / 是否可停止 / 服务类型 |
|
|
787
|
+
|
|
788
|
+
### 其他 API
|
|
789
|
+
|
|
790
|
+
| API | 返回值 | 说明 |
|
|
791
|
+
|---|---|---|
|
|
792
|
+
| `getAllInfo()` | 上述全部模块汇总对象 | 并行获取,单模块失败不影响其他 |
|
|
793
|
+
| `getAllHardwareInfo()` | 完整硬件传感器树 | OHM 全硬件(主板/CPU/内存/硬盘/风扇等),需管理员 |
|
|
794
|
+
| `createCpuTempDaemon()` | `CpuTempDaemon` | CPU 温度独立常驻进程(~60ms/次),需管理员 |
|
|
795
|
+
| `createCpuTempMonitor()` | `CpuTempMonitor` | CPU 温度高频监控器(EventEmitter) |
|
|
796
|
+
| `createSysInfoDaemon()` | `SysInfoDaemon` | 统一常驻进程(所有模块复用,缓存可配) |
|
|
797
|
+
| `listDriveLetters()` | `string[]` | 列出当前所有盘符,如 `['C:', 'D:']` |
|
|
798
|
+
|
|
799
|
+
## 原理
|
|
800
|
+
|
|
801
|
+
### CPU 温度
|
|
802
|
+
|
|
803
|
+
Windows 没有用户态 API 读 CPU 核心温度。OpenHardwareMonitor 自带 WinRing0 内核驱动,运行时临时加载,通过 `DeviceIoControl` 执行 `RDMSR` 读 MSR 寄存器:
|
|
804
|
+
|
|
805
|
+
- `IA32_THERM_STATUS` (0x19C) — 每核心 DTS 温度
|
|
806
|
+
- `IA32_PACKAGE_THERM_STATUS` (0x1B1) — 封装温度
|
|
807
|
+
- `IA32_TEMPERATURE_TARGET` (0x1A2) — TjMax
|
|
808
|
+
- RAPL 寄存器 — 功耗
|
|
809
|
+
|
|
810
|
+
温度 = TjMax - DTS差值,精度 ±1-2°C。用完即卸载驱动不残留。
|
|
811
|
+
|
|
812
|
+
### 其他系统信息
|
|
813
|
+
|
|
814
|
+
通过 Windows WMI/CIM(`Get-CimInstance`)和性能计数器获取,无需管理员、无需驱动:
|
|
815
|
+
|
|
816
|
+
- 系统/硬件信息 → `Win32_OperatingSystem`、`Win32_ComputerSystem`、`Win32_BIOS`、`Win32_BaseBoard`、`Win32_Processor`
|
|
817
|
+
- 内存 → `Win32_PhysicalMemory`、`Win32_PhysicalMemoryArray`
|
|
818
|
+
- 硬盘 → `Win32_DiskDrive`、`Win32_LogicalDisk`、`Win32_PerfFormattedData_PerfDisk_PhysicalDisk`
|
|
819
|
+
- 网络 → `Win32_NetworkAdapter`、`Win32_NetworkAdapterConfiguration`、`Win32_PerfFormattedData_Tcpip_NetworkInterface`、`netsh wlan`
|
|
820
|
+
- 电池 → `Win32_Battery`、`Win32_PortableBattery`、`powercfg`
|
|
821
|
+
- 显卡 → `Win32_VideoController`、`Win32_DesktopMonitor`
|
|
822
|
+
- USB → `Win32_USBController`、`Win32_PnPEntity`
|
|
823
|
+
- 进程 → koffi 直调 Toolhelp32/psapi/GetProcessTimes(默认)或 `Get-Process`/`Win32_Process`(wmi 后端)
|
|
824
|
+
- 服务 → `Win32_Service`
|
|
825
|
+
- 磁盘插拔 → WMI 事件 `Win32_VolumeChangeEvent` + 轮询兜底
|
|
826
|
+
- 公网 IP → DNS 查询(OpenDNS/Google DNS)+ HTTPS 兜底
|
|
827
|
+
|
|
828
|
+
## 注意事项
|
|
829
|
+
|
|
830
|
+
- **CPU 真实温度需管理员**,非管理员时 `getCpuTemp()` 自动降级到 ACPI 热区温度(`isCoreTemp: false`)
|
|
831
|
+
- **驱动不残留**,每次 OHM 调用后自动卸载 WinRing0 驱动
|
|
832
|
+
- **OHM 0.9.6 硬件局限**:较新的 GPU/NVMe/笔记本 EC 可能支持有限,需要更新硬件可换 LibreHardwareMonitor
|
|
833
|
+
- **内存焊死的笔记本**:WMI 可能将每个内存颗粒识别为一条,stickCount 偏多
|
|
834
|
+
- **电池健康度**:部分笔记本 WMI 不暴露设计容量,healthPercent 为 null
|
|
835
|
+
- **进程 CPU%**:`includeCpu=true` 时第一次调用返回 0(建立基线),1 秒后正常
|
|
836
|
+
- **杀进程**:`killProcess` 自动拒绝结束当前进程自身和父进程,防止误杀
|
|
837
|
+
- **公网 IP**:DNS 查询可能被防火墙拦截,自动降级到 HTTPS 兜底
|
|
838
|
+
|
|
839
|
+
## 测试
|
|
840
|
+
|
|
841
|
+
```bash
|
|
842
|
+
# CPU 温度基础测试(需管理员)
|
|
843
|
+
node test/test.js
|
|
844
|
+
|
|
845
|
+
# 常驻模式性能测试(需管理员)
|
|
846
|
+
node test/test-daemon.js
|
|
847
|
+
|
|
848
|
+
# 监控器功能测试(需管理员)
|
|
849
|
+
node test/test-monitor.js
|
|
850
|
+
|
|
851
|
+
# 全模块综合测试(无需管理员,CPU 温度自动降级)
|
|
852
|
+
node test/test-all.js
|
|
853
|
+
|
|
854
|
+
# 新增功能综合测试(进程增强/进程操作/磁盘监听/进程图标)
|
|
855
|
+
node test/test-new-features.js
|
|
856
|
+
|
|
857
|
+
# 统一常驻服务测试
|
|
858
|
+
node test/test-service.js
|
|
859
|
+
|
|
860
|
+
# 进程名/端口杀进程测试
|
|
861
|
+
node test/test-kill-name.js
|
|
862
|
+
|
|
863
|
+
# Express 调试服务(端口 3210,Vue 3 仪表盘)
|
|
864
|
+
node test/server.js
|
|
865
|
+
```
|
|
866
|
+
|
|
867
|
+
或使用 npm scripts:
|
|
868
|
+
|
|
869
|
+
```bash
|
|
870
|
+
npm test
|
|
871
|
+
npm run test:daemon
|
|
872
|
+
npm run test:monitor
|
|
873
|
+
npm run test:all
|
|
874
|
+
npm run test:new
|
|
875
|
+
npm run test:monitor
|
|
876
|
+
npm run server
|
|
877
|
+
```
|
|
878
|
+
|
|
879
|
+
## 支持作者
|
|
880
|
+
|
|
881
|
+
这个项目从"只想读个 CPU 温度"开始,一路踩坑扩展到现在 30+ API 的全维度硬件信息库,全是业余时间一点点堆出来的。
|
|
882
|
+
|
|
883
|
+
如果你觉得它帮你省了调研时间、避开了那些坑(比如 Windows 真实核心温度要读 MSR 寄存器、koffi 直调 Win32 API 比 WMI 快 4 倍这些),欢迎请作者喝杯咖啡 ☕
|
|
884
|
+
|
|
885
|
+
你的支持会用来:
|
|
886
|
+
- 持续修复 bug、跟进新硬件兼容
|
|
887
|
+
- 推进 Linux / macOS 跨平台支持
|
|
888
|
+
- 补充更多传感器和系统信息
|
|
889
|
+
- 买咖啡续命(真的需要,开源不容易)
|
|
890
|
+
|
|
891
|
+
| 微信 | 支付宝 |
|
|
892
|
+
|:---:|:---:|
|
|
893
|
+
|  |  |
|
|
894
|
+
|  |  |
|
|
895
|
+
|
|
896
|
+
一块两块都是鼓励,感谢 🙏
|
|
897
|
+
|
|
898
|
+
## 致谢
|
|
899
|
+
|
|
900
|
+
- [OpenHardwareMonitor](https://openhardwaremonitor.org/) — 开源硬件监控库,CPU 温度功能使用其 DLL
|
|
901
|
+
- [koffi](https://koffi.dev/) — 快速 Node.js C FFI 库,进程枚举直调 Win32 API
|
|
902
|
+
- [fkill](https://github.com/sindresorhus/fkill) — 跨平台杀进程库,支持 PID/端口/名称
|
|
903
|
+
- WinRing0 — 内核驱动,允许用户态程序执行特权指令
|
|
904
|
+
|
|
905
|
+
## License
|
|
906
|
+
|
|
907
|
+
MIT
|