@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.
Files changed (47) hide show
  1. package/README.md +907 -0
  2. package/bin/OpenHardwareMonitorLib.dll +0 -0
  3. package/index.js +192 -0
  4. package/lib/allhardware.js +35 -0
  5. package/lib/backend-usage.js +103 -0
  6. package/lib/battery.js +76 -0
  7. package/lib/disk-watcher.js +156 -0
  8. package/lib/disk.js +77 -0
  9. package/lib/gpu.js +70 -0
  10. package/lib/hardware-service.js +284 -0
  11. package/lib/memory.js +59 -0
  12. package/lib/monitor.js +176 -0
  13. package/lib/network.js +75 -0
  14. package/lib/ohm-daemon.js +208 -0
  15. package/lib/ohm.js +41 -0
  16. package/lib/perfctr.js +43 -0
  17. package/lib/process-icon.js +76 -0
  18. package/lib/process-ops.js +218 -0
  19. package/lib/processes.js +232 -0
  20. package/lib/ps.js +93 -0
  21. package/lib/public-ip.js +124 -0
  22. package/lib/services.js +43 -0
  23. package/lib/sysinfo-daemon.js +188 -0
  24. package/lib/system.js +77 -0
  25. package/lib/usb.js +49 -0
  26. package/lib/win32-procs.js +241 -0
  27. package/package.json +50 -0
  28. package/scripts/get-all-hardware.ps1 +98 -0
  29. package/scripts/get-lhm-temp.ps1 +119 -0
  30. package/scripts/ohm-daemon.ps1 +141 -0
  31. package/scripts/sysinfo-daemon.ps1 +386 -0
  32. package/test/check-bugs.js +182 -0
  33. package/test/public/gj.pay.ali.jpg +0 -0
  34. package/test/public/gj.pay.wx.jpg +0 -0
  35. package/test/public/index.html +996 -0
  36. package/test/public/zdl.pay.ali.jpg +0 -0
  37. package/test/public/zdl.pay.wx.jpg +0 -0
  38. package/test/scan-encoding.js +77 -0
  39. package/test/server.js +255 -0
  40. package/test/test-all.js +180 -0
  41. package/test/test-daemon.js +51 -0
  42. package/test/test-kill-name.js +30 -0
  43. package/test/test-monitor.js +78 -0
  44. package/test/test-new-features.js +93 -0
  45. package/test/test-service.js +91 -0
  46. package/test/test-sysinfo-daemon.js +95 -0
  47. package/test/test.js +63 -0
Binary file
Binary file
@@ -0,0 +1,77 @@
1
+ /**
2
+ * 扫描项目里所有 .js / .ps1 / .md 文件,检测中文乱码
3
+ * 乱码特征:包含典型的 GBK→UTF-8 误码字符
4
+ */
5
+ const fs = require('fs');
6
+ const path = require('path');
7
+
8
+ const ROOT = path.join(__dirname, '..');
9
+ const EXCLUDE = ['node_modules', '.git'];
10
+
11
+ // 典型乱码字符(GBK字节被当UTF-8解析后的常见字符)
12
+ const GARBLE_CHARS = ['鍚', '缁', '鏈', '鐩', '鎻', '掓', '嫈', '浜', '嬩', '欢', '浠', '〃', '樺', '凡', '姩', '閿', '欒', '璇', '锋', '眰', '鍙', '傛', '暟', '鎴', '愬', '姛', '澶', '辫', '触', '鏁', '版', '嵎', '鍔', '犺', '浇', '涓?', '闂', '鍧?', '鍧楋', '紙', '級', '锛', '堬', '紝', '偣', '鍨', '傚簲', '鍝嶅簲', '搴旂敤', '搴旂敤绋嬪簭', '繍琛岋級', '杩愯', '杩涚▼', '繘绋嬪垪琛ㄦ椂', '繘绋嬪垪琛ㄦ椂闂村寲', '闆嗗悎鎵€鏈夋ā鍧楋級', '鏁村悎鎵€鏈夋ā鍧楋級', '甯搁┗鐩戞帶鍣紙', '鐩戞帶鍣ㄥ惎鍔ㄥけ璐?', '鐩戞帶鍣ㄥ惎鍔ㄥけ璐?', '浠ョ悊鍛樹韩杩愯鍙幏鍙栫湡瀹?CPU 鏍稿績娓╁害', '鏈湴璁块棶', '鍋ュ悍妫€鏌?', '鎻愮ず', '姝e湪鍏抽棴', '浼橀泤鍏抽棴', '鍚姩鏈嶅姟', 'API 鎺ュ彛', '绯荤粺淇℃伅锛堜唬鐞嗗埌缁熶竴鐩戞帶鍣紙級', '缂哄皯 path', '缂哄皯 paths 鏁扮粍', 'CPU 娓╁害锛堜粠缁熶竴鐩戞帶鍣ㄨ幏鍙栨渶鏂板€硷級', '鍏綉 IP', '纾佺洏鎻掓嫈浜嬩欢锛圫SE 瀹炴椂鎺ㄩ€侊級', 'OHM 鍏ㄧ‖浠朵紶鎰熷櫒锛堜富鏉?CPU/RAM/HDD 鎵€鏈変紶鎰熷櫒鍊硷級', '鍚姩'];
13
+
14
+ function scanDir(dir) {
15
+ const results = [];
16
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
17
+ for (const entry of entries) {
18
+ if (EXCLUDE.includes(entry.name)) continue;
19
+ const fullPath = path.join(dir, entry.name);
20
+ if (entry.isDirectory()) {
21
+ results.push(...scanDir(fullPath));
22
+ } else if (/\.(js|ps1|md|json)$/.test(entry.name)) {
23
+ const rel = path.relative(ROOT, fullPath);
24
+ try {
25
+ const buf = fs.readFileSync(fullPath);
26
+ const hasBom = buf.length >= 3 && buf[0] === 0xEF && buf[1] === 0xBB && buf[2] === 0xBF;
27
+ const content = buf.toString('utf8');
28
+ let hasGarble = false;
29
+ let garbleSample = '';
30
+ for (const ch of GARBLE_CHARS) {
31
+ if (content.includes(ch)) {
32
+ hasGarble = true;
33
+ const idx = content.indexOf(ch);
34
+ garbleSample = content.substring(Math.max(0, idx - 5), idx + 15).replace(/\n/g, '\\n');
35
+ break;
36
+ }
37
+ }
38
+ // 检查是否有替换字符 U+FFFD
39
+ if (content.includes('\uFFFD')) {
40
+ hasGarble = true;
41
+ if (!garbleSample) garbleSample = '包含 U+FFFD 替换字符';
42
+ }
43
+ results.push({ file: rel, hasBom, hasGarble, garbleSample, size: buf.length });
44
+ } catch (e) {
45
+ results.push({ file: rel, error: e.message });
46
+ }
47
+ }
48
+ }
49
+ return results;
50
+ }
51
+
52
+ const results = scanDir(ROOT);
53
+ console.log('=== 文件编码扫描结果 ===\n');
54
+ const garbled = results.filter(r => r.hasGarble);
55
+ const withBom = results.filter(r => r.hasBom && !r.hasGarble);
56
+ const ok = results.filter(r => !r.hasGarble && !r.hasBom);
57
+
58
+ console.log(`总文件数: ${results.length}`);
59
+ console.log(`有乱码: ${garbled.length}`);
60
+ console.log(`有BOM但无乱码: ${withBom.length}`);
61
+ console.log(`正常(无BOM无乱码): ${ok.length}`);
62
+
63
+ if (garbled.length) {
64
+ console.log('\n=== 需要修复的乱码文件 ===');
65
+ garbled.forEach(r => {
66
+ console.log(` [乱码] ${r.file} (${r.size}字节) BOM:${r.hasBom}`);
67
+ console.log(` 样本: ${r.garbleSample}`);
68
+ });
69
+ }
70
+
71
+ if (withBom.length) {
72
+ console.log('\n=== 有BOM但无乱码(建议去BOM)===');
73
+ withBom.forEach(r => console.log(` [BOM] ${r.file}`));
74
+ }
75
+
76
+ console.log('\n=== 正常文件 ===');
77
+ ok.forEach(r => console.log(` [OK] ${r.file}`));
package/test/server.js ADDED
@@ -0,0 +1,255 @@
1
+ /**
2
+ * hardware-info Express 服务
3
+ * 启动: node test/server.js
4
+ * 访问: http://localhost:3210
5
+ */
6
+ const express = require('express');
7
+ const path = require('path');
8
+ const { createHardwareService } = require('../index');
9
+
10
+ const app = express();
11
+ const PORT = process.env.PORT || 3210;
12
+
13
+ // 统一常驻监控器(整合所有模块)
14
+ let service = null;
15
+ let serviceReady = false;
16
+
17
+ // 磁盘插拔事件缓存(用于 SSE)
18
+ let diskEvents = [];
19
+ const sseClients = new Set();
20
+
21
+ async function initService() {
22
+ try {
23
+ service = await createHardwareService({
24
+ cpuTempInterval: 1000,
25
+ diskWatchInterval: 2000
26
+ });
27
+ serviceReady = true;
28
+
29
+ // 监听磁盘插拔事件
30
+ service.on('disk-change', (info) => {
31
+ const event = { time: new Date().toISOString(), ...info };
32
+ diskEvents.push(event);
33
+ if (diskEvents.length > 50) diskEvents.shift();
34
+ // 推送给所有 SSE 客户端
35
+ for (const res of sseClients) {
36
+ res.write(`data: ${JSON.stringify(event)}\n\n`);
37
+ }
38
+ });
39
+
40
+ console.log('[hardware-info] 统一监控器已启动');
41
+ } catch (e) {
42
+ console.error('[hardware-info] 监控器启动失败:', e.message);
43
+ }
44
+ }
45
+
46
+ // 托管静态文件
47
+ app.use(express.static(path.join(__dirname, 'public')));
48
+
49
+ // ========== API 接口 ==========
50
+
51
+ // 系统信息(代理到统一监控器)
52
+ app.get('/api/system', async (req, res) => {
53
+ try { res.json({ success: true, data: await service.getSystem() }); }
54
+ catch (e) { res.status(500).json({ success: false, error: e.message }); }
55
+ });
56
+
57
+ app.get('/api/memory', async (req, res) => {
58
+ try { res.json({ success: true, data: await service.getMemory() }); }
59
+ catch (e) { res.status(500).json({ success: false, error: e.message }); }
60
+ });
61
+
62
+ app.get('/api/disk', async (req, res) => {
63
+ try { res.json({ success: true, data: await service.getDisk() }); }
64
+ catch (e) { res.status(500).json({ success: false, error: e.message }); }
65
+ });
66
+
67
+ app.get('/api/network', async (req, res) => {
68
+ try { res.json({ success: true, data: await service.getNetwork() }); }
69
+ catch (e) { res.status(500).json({ success: false, error: e.message }); }
70
+ });
71
+
72
+ app.get('/api/battery', async (req, res) => {
73
+ try { res.json({ success: true, data: await service.getBattery() }); }
74
+ catch (e) { res.status(500).json({ success: false, error: e.message }); }
75
+ });
76
+
77
+ app.get('/api/gpu', async (req, res) => {
78
+ try { res.json({ success: true, data: await service.getGpu() }); }
79
+ catch (e) { res.status(500).json({ success: false, error: e.message }); }
80
+ });
81
+
82
+ app.get('/api/usb', async (req, res) => {
83
+ try { res.json({ success: true, data: await service.getUsb() }); }
84
+ catch (e) { res.status(500).json({ success: false, error: e.message }); }
85
+ });
86
+
87
+ app.get('/api/services', async (req, res) => {
88
+ try {
89
+ const runningOnly = req.query.running === '1';
90
+ res.json({ success: true, data: await service.getServices({ runningOnly }) });
91
+ } catch (e) { res.status(500).json({ success: false, error: e.message }); }
92
+ });
93
+
94
+ // 进程(默认带 CPU%,支持按名称聚合)
95
+ app.get('/api/processes', async (req, res) => {
96
+ try {
97
+ const top = parseInt(req.query.top) || 20;
98
+ const sortBy = req.query.sort || 'memory';
99
+ const groupByName = req.query.group === '1';
100
+ const data = await service.getProcesses({ top, sortBy, groupByName });
101
+ res.json({ success: true, data });
102
+ } catch (e) { res.status(500).json({ success: false, error: e.message }); }
103
+ });
104
+
105
+ // 杀进程(支持 PID、端口号或进程名)
106
+ app.post('/api/processes/kill', express.json(), async (req, res) => {
107
+ try {
108
+ const { pid, port, protocol, name } = req.body;
109
+ if (!pid && !port && !name) return res.status(400).json({ success: false, error: '需要 pid、port 或 name 参数' });
110
+ let input;
111
+ if (port) input = { port, protocol: protocol || 'all' };
112
+ else if (name) input = { name };
113
+ else input = pid;
114
+ const result = await service.killProcess(input);
115
+ res.json({ success: result.ok, ...result });
116
+ } catch (e) { res.status(500).json({ success: false, error: e.message }); }
117
+ });
118
+
119
+ // 查找占用指定端口的进程 PID
120
+ app.get('/api/processes/find-by-port', async (req, res) => {
121
+ try {
122
+ const port = parseInt(req.query.port, 10);
123
+ const protocol = req.query.protocol || 'all';
124
+ if (!port || port < 1 || port > 65535) return res.status(400).json({ success: false, error: '无效的端口号' });
125
+ const pids = await service.findPidsByPort(port, protocol);
126
+ res.json({ success: true, port, protocol, pids });
127
+ } catch (e) { res.status(500).json({ success: false, error: e.message }); }
128
+ });
129
+
130
+ // 按进程名查找 PID
131
+ app.get('/api/processes/find-by-name', (req, res) => {
132
+ try {
133
+ const name = req.query.name;
134
+ if (!name) return res.status(400).json({ success: false, error: '需要 name 参数' });
135
+ const pids = service.findPidsByName(name);
136
+ res.json({ success: true, name, pids });
137
+ } catch (e) { res.status(500).json({ success: false, error: e.message }); }
138
+ });
139
+
140
+ // 打开文件所在位置
141
+ app.post('/api/processes/reveal', express.json(), (req, res) => {
142
+ try {
143
+ const { path: filePath } = req.body;
144
+ if (!filePath) return res.status(400).json({ success: false, error: '缺少 path' });
145
+ const result = service.showItemInFolder(filePath);
146
+ res.json({ success: result.ok, ...result });
147
+ } catch (e) { res.status(500).json({ success: false, error: e.message }); }
148
+ });
149
+
150
+ // 进程图标(单个)
151
+ app.get('/api/processes/icon', async (req, res) => {
152
+ try {
153
+ const { path: filePath } = req.query;
154
+ if (!filePath) return res.status(400).json({ success: false, error: '缺少 path' });
155
+ const icon = await require('../index').getProcessIcon(filePath);
156
+ res.json({ success: true, icon });
157
+ } catch (e) { res.status(500).json({ success: false, error: e.message }); }
158
+ });
159
+
160
+ // 进程图标(批量,一次 PowerShell 提取多个)
161
+ app.post('/api/processes/icons', express.json(), async (req, res) => {
162
+ try {
163
+ const paths = Array.isArray(req.body?.paths) ? req.body.paths.filter(Boolean) : [];
164
+ if (!paths.length) return res.status(400).json({ success: false, error: '缺少 paths 数组' });
165
+ const icons = await require('../index').getProcessIcons(paths);
166
+ res.json({ success: true, icons });
167
+ } catch (e) { res.status(500).json({ success: false, error: e.message }); }
168
+ });
169
+
170
+ // CPU 温度(从统一监控器获取最新值)
171
+ app.get('/api/cpu-temp', (req, res) => {
172
+ try {
173
+ const data = service.getCpuTemp();
174
+ res.json({ success: true, data });
175
+ } catch (e) { res.status(500).json({ success: false, error: e.message }); }
176
+ });
177
+
178
+ // 公网 IP
179
+ app.get('/api/public-ip', async (req, res) => {
180
+ try {
181
+ const ip = await service.getPublicIp();
182
+ res.json({ success: true, ip });
183
+ } catch (e) { res.status(500).json({ success: false, error: e.message }); }
184
+ });
185
+
186
+ // 一键汇总
187
+ app.get('/api/all', async (req, res) => {
188
+ try {
189
+ const includeProcesses = req.query.processes === '1';
190
+ const includeServices = req.query.services === '1';
191
+ const data = await service.getAll({ includeProcesses, includeServices });
192
+ res.json({ success: true, data });
193
+ } catch (e) { res.status(500).json({ success: false, error: e.message }); }
194
+ });
195
+
196
+ // 磁盘插拔事件(SSE 实时推送)
197
+ app.get('/api/disk-events', (req, res) => {
198
+ res.setHeader('Content-Type', 'text/event-stream');
199
+ res.setHeader('Cache-Control', 'no-cache');
200
+ res.setHeader('Connection', 'keep-alive');
201
+ res.write(`data: ${JSON.stringify({ type: 'history', events: diskEvents })}\n\n`);
202
+ sseClients.add(res);
203
+ req.on('close', () => sseClients.delete(res));
204
+ });
205
+
206
+ // 服务状态
207
+ app.get('/api/status', (req, res) => {
208
+ res.json({ success: true, ready: serviceReady, status: service ? service.getStatus() : null });
209
+ });
210
+
211
+ // OHM 全硬件传感器(主板/CPU/RAM/HDD 所有传感器值)
212
+ app.get('/api/all-hardware', async (req, res) => {
213
+ try {
214
+ const { getAllHardwareInfo } = require('../index');
215
+ const data = await getAllHardwareInfo();
216
+ res.json({ success: true, data });
217
+ } catch (e) { res.status(500).json({ success: false, error: e.message }); }
218
+ });
219
+
220
+ // 健康检查
221
+ app.get('/api/health', (req, res) => {
222
+ res.json({ success: true, ready: serviceReady, uptime: process.uptime(), timestamp: new Date().toISOString() });
223
+ });
224
+
225
+ // 后端资源占用(Node.js + 子进程,同步高频安全)
226
+ app.get('/api/backend-usage', (req, res) => {
227
+ try {
228
+ const { getBackendUsage } = require('../index');
229
+ res.json({ success: true, data: getBackendUsage() });
230
+ } catch (e) { res.status(500).json({ success: false, error: e.message }); }
231
+ });
232
+
233
+ // 启动服务
234
+ async function start() {
235
+ await initService();
236
+ app.listen(PORT, () => {
237
+ console.log('');
238
+ console.log(' hardware-info 仪表板已启动(统一监控器模式)');
239
+ console.log(' ----------------------------------------');
240
+ console.log(` 本地访问: http://localhost:${PORT}`);
241
+ console.log(` 健康检查: http://localhost:${PORT}/api/health`);
242
+ console.log('');
243
+ console.log(' 提示: 以管理员身份运行可获取真实 CPU 核心温度');
244
+ console.log('');
245
+ });
246
+ }
247
+
248
+ // 优雅关闭
249
+ process.on('SIGINT', async () => {
250
+ console.log('\n正在关闭...');
251
+ if (service) await service.close();
252
+ process.exit(0);
253
+ });
254
+
255
+ start();
@@ -0,0 +1,180 @@
1
+ const {
2
+ getSystemInfo,
3
+ getMemoryInfo,
4
+ getDiskInfo,
5
+ getNetworkInfo,
6
+ getBatteryInfo,
7
+ getGpuInfo,
8
+ getUsbInfo,
9
+ getProcesses,
10
+ getServicesInfo,
11
+ getAllInfo,
12
+ getCpuTemp
13
+ } = require('../index');
14
+
15
+ async function main() {
16
+ console.log('=== hardware-info 全模块测试 ===\n');
17
+
18
+ // 1. 系统信息
19
+ console.log('--- 1. 系统信息 ---');
20
+ try {
21
+ const s = await getSystemInfo();
22
+ console.log(` OS: ${s.os.caption} (build ${s.os.buildNumber})`);
23
+ console.log(` 计算机: ${s.computer.manufacturer} ${s.computer.model}`);
24
+ console.log(` 计算机名: ${s.computer.name}`);
25
+ console.log(` BIOS: ${s.bios.manufacturer} ${s.bios.version} (${s.bios.releaseDate?.slice(0, 10)})`);
26
+ console.log(` 主板: ${s.motherboard.manufacturer} ${s.motherboard.product}`);
27
+ console.log(` CPU: ${s.cpu.name}`);
28
+ console.log(` 核心/线程: ${s.cpu.numberOfCores}核 / ${s.cpu.numberOfLogicalProcessors}线程`);
29
+ console.log(` L2/L3缓存: ${s.cpu.l2CacheKB}KB / ${s.cpu.l3CacheKB}KB`);
30
+ console.log(` 开机时长: ${s.os.uptimeDays} 天`);
31
+ console.log(` 电源计划: ${s.powerPlan}`);
32
+ } catch (e) { console.log(' 失败:', e.message); }
33
+
34
+ // 2. CPU 温度
35
+ console.log('\n--- 2. CPU 温度 ---');
36
+ try {
37
+ const c = await getCpuTemp();
38
+ console.log(` 来源: ${c.source} (isCoreTemp: ${c.isCoreTemp})`);
39
+ console.log(` 封装: ${c.temperature.package}°C | 最高核心: ${c.temperature.maxCore}°C`);
40
+ if (c.temperature.cores?.length > 0) {
41
+ console.log(` 每核心: ${c.temperature.cores.map(x => `${x.name}=${x.value}°C`).join(', ')}`);
42
+ }
43
+ const totalLoad = c.load?.find(l => l.name === 'CPU Total');
44
+ const pkgPower = c.power?.find(p => p.name === 'CPU Package');
45
+ console.log(` 负载: ${totalLoad?.value}% | 功耗: ${pkgPower?.value}W`);
46
+ } catch (e) { console.log(' 失败:', e.message); }
47
+
48
+ // 3. 内存
49
+ console.log('\n--- 3. 内存 ---');
50
+ try {
51
+ const m = await getMemoryInfo();
52
+ console.log(` 总内存: ${m.totalPhysicalGB}GB | 已用: ${m.usedPhysicalGB}GB (${m.usedPercent}%)`);
53
+ console.log(` 虚拟内存: ${m.totalVirtualGB}GB | 可用: ${m.freeVirtualGB}GB`);
54
+ console.log(` 内存条数: ${m.stickCount}`);
55
+ m.sticks.forEach((s, i) => {
56
+ console.log(` 插槽${i + 1}: ${s.capacityGB}GB ${s.speedMHz}MHz ${s.manufacturer} ${s.partNumber} (${s.deviceLocator})`);
57
+ });
58
+ if (m.array) console.log(` 最大支持: ${m.array.maxCapacityGB}GB / ${m.array.memoryDevices}插槽`);
59
+ } catch (e) { console.log(' 失败:', e.message); }
60
+
61
+ // 4. 硬盘
62
+ console.log('\n--- 4. 硬盘 ---');
63
+ try {
64
+ const d = await getDiskInfo();
65
+ console.log(` 物理磁盘: ${d.diskCount} 块 | 总容量: ${d.totalSizeGB}GB`);
66
+ d.physicalDisks.forEach(disk => {
67
+ console.log(` 磁盘${disk.index}: ${disk.model} | ${disk.sizeGB}GB | ${disk.interfaceType} | 盘符: ${disk.driveLetters.join(',') || '无'}`);
68
+ if (disk.readBytesPerSec != null) {
69
+ const MB = 1024 * 1024;
70
+ console.log(` 读: ${(disk.readBytesPerSec / MB).toFixed(1)}MB/s | 写: ${(disk.writeBytesPerSec / MB).toFixed(1)}MB/s | 活跃: ${disk.percentActive}%`);
71
+ }
72
+ });
73
+ console.log(` 逻辑分区: ${d.logicalDrives.length} 个`);
74
+ d.logicalDrives.forEach(ld => {
75
+ console.log(` ${ld.drive} ${ld.volumeName || ''}: ${ld.usedGB}/${ld.sizeGB}GB (${ld.usedPercent}%) ${ld.fileSystem}`);
76
+ });
77
+ } catch (e) { console.log(' 失败:', e.message); }
78
+
79
+ // 5. 网络
80
+ console.log('\n--- 5. 网络 ---');
81
+ try {
82
+ const n = await getNetworkInfo();
83
+ console.log(` 网卡: ${n.adapterCount} 块 | 活跃: ${n.activeAdapterCount} 块`);
84
+ const MB = 1024 * 1024;
85
+ console.log(` 总下载: ${(n.totalDownloadBytesPerSec / MB).toFixed(2)}MB/s | 总上传: ${(n.totalUploadBytesPerSec / MB).toFixed(2)}MB/s`);
86
+ if (n.wifi) console.log(` WiFi: ${n.wifi.ssId} | 信号: ${n.wifi.signalPercent}% | 频道: ${n.wifi.channel}`);
87
+ n.adapters.filter(a => a.status === 2 && a.ipAddresses?.length > 0).slice(0, 3).forEach(a => {
88
+ console.log(` [活跃] ${a.connectionName || a.name}: ${a.ipAddresses[0]} | MAC: ${a.macAddress} | ${a.speedMbps}Mbps`);
89
+ });
90
+ } catch (e) { console.log(' 失败:', e.message); }
91
+
92
+ // 6. 电池
93
+ console.log('\n--- 6. 电池 ---');
94
+ try {
95
+ const b = await getBatteryInfo();
96
+ if (!b.hasBattery) {
97
+ console.log(' 无电池(台式机)');
98
+ } else {
99
+ console.log(` 电池数: ${b.batteries.length} | 总电量: ${b.overallChargePercent}% | 充电中: ${b.isCharging}`);
100
+ b.batteries.forEach((bat, i) => {
101
+ console.log(` 电池${i + 1}: ${bat.name} | 状态: ${bat.batteryStatus} | 电量: ${bat.chargePercent}%`);
102
+ if (bat.healthPercent != null) console.log(` 健康度: ${bat.healthPercent}% | 设计: ${bat.designCapacitymWh}mWh | 满充: ${bat.fullChargeCapacitymWh}mWh`);
103
+ if (bat.cycleCount != null) console.log(` 循环次数: ${bat.cycleCount}`);
104
+ if (bat.estimatedRunTimeMinutes > 0) console.log(` 预计续航: ${bat.estimatedRunTimeMinutes}分钟`);
105
+ console.log(` 厂商: ${bat.manufacturer} | 化学: ${bat.chemistry}`);
106
+ });
107
+ }
108
+ console.log(` 电源计划: ${b.powerPlan}`);
109
+ } catch (e) { console.log(' 失败:', e.message); }
110
+
111
+ // 7. 显卡/显示器
112
+ console.log('\n--- 7. 显卡/显示器 ---');
113
+ try {
114
+ const g = await getGpuInfo();
115
+ console.log(` 显卡: ${g.gpuCount} 块 | 显示器: ${g.monitorCount} 台`);
116
+ g.gpus.forEach(gpu => {
117
+ console.log(` GPU: ${gpu.name} | 显存: ${gpu.adapterRAMMB}MB | 驱动: ${gpu.driverVersion}`);
118
+ console.log(` 当前: ${gpu.currentHorizontalResolution}x${gpu.currentVerticalResolution}@${gpu.currentRefreshRate}Hz ${gpu.currentBitsPerPixel}bit`);
119
+ });
120
+ g.monitors.forEach((m, i) => {
121
+ console.log(` 显示器${i + 1}: ${m.name} | ${m.screenWidth}x${m.screenHeight}`);
122
+ });
123
+ } catch (e) { console.log(' 失败:', e.message); }
124
+
125
+ // 8. USB
126
+ console.log('\n--- 8. USB 设备 ---');
127
+ try {
128
+ const u = await getUsbInfo();
129
+ console.log(` USB 控制器: ${u.controllerCount} 个 | USB 设备: ${u.deviceCount} 个`);
130
+ u.devices.slice(0, 8).forEach(d => {
131
+ console.log(` - ${d.name} [${d.status}]`);
132
+ });
133
+ if (u.deviceCount > 8) console.log(` ... 还有 ${u.deviceCount - 8} 个`);
134
+ } catch (e) { console.log(' 失败:', e.message); }
135
+
136
+ // 9. 进程 Top 10
137
+ console.log('\n--- 9. 进程 Top 10(按内存)---');
138
+ try {
139
+ const p = await getProcesses({ top: 10, sortBy: 'memory' });
140
+ console.log(` 总进程数: ${p.total} | 返回: ${p.returned}`);
141
+ p.processes.forEach((proc, i) => {
142
+ console.log(` ${i + 1}. ${proc.name} (PID ${proc.pid}) | 内存: ${proc.memoryMB}MB | CPU: ${proc.cpuSeconds}s | 线程: ${proc.threads}`);
143
+ });
144
+ } catch (e) { console.log(' 失败:', e.message); }
145
+
146
+ // 10. 服务统计
147
+ console.log('\n--- 10. 服务统计 ---');
148
+ try {
149
+ const s = await getServicesInfo();
150
+ console.log(` 总服务: ${s.total} | 运行中: ${s.running} | 已停止: ${s.stopped}`);
151
+ } catch (e) { console.log(' 失败:', e.message); }
152
+
153
+ // 11. getAllInfo 汇总
154
+ console.log('\n--- 11. getAllInfo() 汇总测试 ---');
155
+ try {
156
+ const all = await getAllInfo({ includeProcesses: true, processTop: 5 });
157
+ console.log(` 时间戳: ${all.timestamp}`);
158
+ console.log(` 系统: ${all.system ? 'OK' : '失败'}`);
159
+ console.log(` CPU: ${all.cpu ? `${all.cpu.temperature.maxCore}°C` : '失败'}`);
160
+ console.log(` 内存: ${all.memory ? `${all.memory.usedPercent}%` : '失败'}`);
161
+ console.log(` 硬盘: ${all.disk ? `${all.disk.diskCount}块` : '失败'}`);
162
+ console.log(` 网络: ${all.network ? `${all.network.activeAdapterCount}活跃` : '失败'}`);
163
+ console.log(` 电池: ${all.battery ? (all.battery.hasBattery ? `${all.battery.overallChargePercent}%` : '无电池') : '失败'}`);
164
+ console.log(` 显卡: ${all.gpu ? `${all.gpu.gpuCount}块` : '失败'}`);
165
+ console.log(` USB: ${all.usb ? `${all.usb.deviceCount}设备` : '失败'}`);
166
+ console.log(` 进程: ${all.processes ? `${all.processes.total}个` : '未包含/失败'}`);
167
+ if (all.errors) {
168
+ console.log(` 失败模块: ${Object.entries(all.errors).map(([k, v]) => `${k}: ${v}`).join('; ')}`);
169
+ } else {
170
+ console.log(' 全部模块成功!');
171
+ }
172
+ } catch (e) { console.log(' 失败:', e.message); }
173
+
174
+ console.log('\n=== 测试完成 ===');
175
+ }
176
+
177
+ main().catch(err => {
178
+ console.error('测试失败:', err);
179
+ process.exit(1);
180
+ });
@@ -0,0 +1,51 @@
1
+ const { getCpuTemp, createCpuTempDaemon } = require('../index');
2
+
3
+ async function main() {
4
+ console.log('=== 常驻模式性能测试 ===\n');
5
+
6
+ // 1. 单次模式延迟(启动进程 + 读一次)
7
+ console.log('--- 单次模式(每次 spawn 新进程)---');
8
+ const singleStart = Date.now();
9
+ const singleResult = await getCpuTemp();
10
+ const singleElapsed = Date.now() - singleStart;
11
+ console.log(`延迟: ${singleElapsed}ms`);
12
+ console.log(`温度: ${singleResult.temperature.maxCore}°C (${singleResult.source})`);
13
+
14
+ // 2. 常驻模式
15
+ console.log('\n--- 常驻模式(进程保持运行)---');
16
+ console.log('启动常驻进程...');
17
+ const daemonStart = Date.now();
18
+ const daemon = await createCpuTempDaemon({ verbose: false });
19
+ const daemonStartElapsed = Date.now() - daemonStart;
20
+ console.log(`启动延迟(含驱动加载): ${daemonStartElapsed}ms`);
21
+
22
+ // 连续读 10 次,测每次延迟
23
+ console.log('\n连续读取 10 次:');
24
+ const delays = [];
25
+ for (let i = 0; i < 10; i++) {
26
+ const start = Date.now();
27
+ const data = await daemon.getCpuTemp();
28
+ const elapsed = Date.now() - start;
29
+ delays.push(elapsed);
30
+ console.log(` 第 ${i + 1} 次: ${elapsed}ms | 封装 ${data.temperature.package}°C | 最高核心 ${data.temperature.maxCore}°C | 负载 ${data.load.find(l => l.name === 'CPU Total')?.value}% | 功耗 ${data.power.find(p => p.name === 'CPU Package')?.value}W`);
31
+ }
32
+
33
+ const avgDelay = Math.round(delays.reduce((a, b) => a + b, 0) / delays.length);
34
+ const minDelay = Math.min(...delays);
35
+ const maxDelay = Math.max(...delays);
36
+
37
+ console.log('\n--- 性能对比 ---');
38
+ console.log(`单次模式延迟: ${singleElapsed}ms`);
39
+ console.log(`常驻模式平均延迟: ${avgDelay}ms (最小 ${minDelay}ms, 最大 ${maxDelay}ms)`);
40
+ console.log(`提速倍数: ${(singleElapsed / avgDelay).toFixed(1)}x`);
41
+
42
+ // 关闭常驻进程
43
+ console.log('\n关闭常驻进程...');
44
+ await daemon.close();
45
+ console.log('已关闭');
46
+ }
47
+
48
+ main().catch(err => {
49
+ console.error('测试失败:', err.message);
50
+ process.exit(1);
51
+ });
@@ -0,0 +1,30 @@
1
+ const { findPidsByName, killProcess } = require('../index');
2
+
3
+ async function test() {
4
+ // 1. 按名称查找 PID
5
+ const pids = findPidsByName('powershell');
6
+ console.log('findPidsByName("powershell"):', pids.length, '个进程');
7
+
8
+ // 2. 带 .exe 后缀
9
+ const pids2 = findPidsByName('powershell.exe');
10
+ console.log('findPidsByName("powershell.exe"):', pids2.length, '个进程');
11
+
12
+ // 3. 不存在的进程名
13
+ const pids3 = findPidsByName('nonexistent_process_xyz');
14
+ console.log('findPidsByName(不存在):', pids3, '(空=未找到)');
15
+
16
+ // 4. 按名称杀(不存在的进程)
17
+ const result = await killProcess({ name: 'nonexistent_process_xyz' });
18
+ console.log('killProcess({name:不存在}):', JSON.stringify(result));
19
+
20
+ // 5. 直接传字符串
21
+ const result2 = await killProcess('nonexistent_process_xyz');
22
+ console.log('killProcess("不存在"):', JSON.stringify(result2));
23
+
24
+ // 6. 混合数组(PID + 名称)
25
+ const result3 = await killProcess([99999, 'nonexistent_process_xyz']);
26
+ console.log('killProcess([pid, name]):', JSON.stringify(result3));
27
+
28
+ process.exit(0);
29
+ }
30
+ test().catch(e => { console.error(e); process.exit(1); });
@@ -0,0 +1,78 @@
1
+ const { createCpuTempMonitor } = require('../index');
2
+
3
+ async function main() {
4
+ console.log('=== CpuTempMonitor 测试 ===\n');
5
+
6
+ // 1. 创建并启动监控器,间隔 500ms
7
+ console.log('[1] 启动监控器,间隔 500ms...');
8
+ const monitor = await createCpuTempMonitor({ interval: 500 });
9
+
10
+ let dataCount = 0;
11
+ monitor.on('start', () => console.log(' -> 事件: start'));
12
+ monitor.on('data', (data) => {
13
+ dataCount++;
14
+ const maxCore = data.temperature.maxCore;
15
+ const pkg = data.temperature.package;
16
+ const load = data.load.find(l => l.name === 'CPU Total')?.value;
17
+ const power = data.power.find(p => p.name === 'CPU Package')?.value;
18
+ console.log(` -> 数据 #${dataCount}: 封装 ${pkg}°C | 最高核心 ${maxCore}°C | 负载 ${load}% | 功耗 ${power}W`);
19
+ });
20
+ monitor.on('error', (e) => console.log(' -> 错误:', e.message));
21
+ monitor.on('pause', () => console.log(' -> 事件: pause'));
22
+ monitor.on('resume', () => console.log(' -> 事件: resume'));
23
+ monitor.on('stop', () => console.log(' -> 事件: stop'));
24
+
25
+ // 等 3 秒,收 ~6 条数据
26
+ await sleep(3000);
27
+ console.log(`\n[2] 3 秒内收到 ${dataCount} 条数据(预期 ~6 条)`);
28
+
29
+ // 3. 动态调整间隔到 200ms
30
+ console.log('\n[3] 动态调整间隔到 200ms...');
31
+ monitor.setInterval(200);
32
+ const countBefore = dataCount;
33
+ await sleep(2000);
34
+ const countAfter = dataCount;
35
+ console.log(` -> 2 秒内收到 ${countAfter - countBefore} 条数据(预期 ~10 条)`);
36
+
37
+ // 4. 暂停
38
+ console.log('\n[4] 暂停监控...');
39
+ monitor.pause();
40
+ const pausedCount = dataCount;
41
+ await sleep(1500);
42
+ console.log(` -> 暂停期间收到 ${dataCount - pausedCount} 条数据(预期 0 条)`);
43
+
44
+ // 5. 立即读取一次
45
+ console.log('\n[5] 暂停状态下立即读取一次...');
46
+ const data = await monitor.readNow();
47
+ console.log(` -> 立即读取: 封装 ${data.temperature.package}°C | 最高核心 ${data.temperature.maxCore}°C`);
48
+
49
+ // 6. 恢复
50
+ console.log('\n[6] 恢复监控...');
51
+ monitor.resume();
52
+ const resumeCount = dataCount;
53
+ await sleep(1000);
54
+ console.log(` -> 恢复后 1 秒内收到 ${dataCount - resumeCount} 条数据(预期 ~5 条,间隔 200ms)`);
55
+
56
+ // 7. 获取最近一次数据
57
+ console.log('\n[7] getLastData():');
58
+ const last = monitor.getLastData();
59
+ console.log(` -> CPU: ${last.cpuName}`);
60
+ console.log(` -> 温度: 封装 ${last.temperature.package}°C, 最高核心 ${last.temperature.maxCore}°C`);
61
+ console.log(` -> isRunning: ${monitor.isRunning()}`);
62
+
63
+ // 8. 停止
64
+ console.log('\n[8] 停止监控...');
65
+ await monitor.stop();
66
+ console.log(` -> isRunning: ${monitor.isRunning()}`);
67
+
68
+ console.log('\n=== 测试完成 ===');
69
+ }
70
+
71
+ function sleep(ms) {
72
+ return new Promise(r => setTimeout(r, ms));
73
+ }
74
+
75
+ main().catch(err => {
76
+ console.error('测试失败:', err.message);
77
+ process.exit(1);
78
+ });