systeminformation 5.31.16 → 5.32.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 +12 -7
- package/lib/audio.js +6 -5
- package/lib/battery.js +6 -2
- package/lib/bluetooth.js +6 -2
- package/lib/cpu.js +68 -45
- package/lib/docker.js +49 -62
- package/lib/dockerSocket.js +56 -261
- package/lib/filesystem.js +32 -23
- package/lib/graphics.js +167 -89
- package/lib/index.d.ts +1 -0
- package/lib/index.js +4 -2
- package/lib/memory.js +6 -3
- package/lib/network.js +19 -5
- package/lib/osinfo.js +20 -9
- package/lib/printer.js +5 -5
- package/lib/processes.js +49 -15
- package/lib/system.js +3 -4
- package/lib/usb.js +0 -4
- package/lib/util.js +32 -14
- package/lib/virtualbox.js +10 -4
- package/lib/wifi.js +32 -19
- package/package.json +4 -3
package/lib/graphics.js
CHANGED
|
@@ -35,6 +35,10 @@ let _resolutionY = 0;
|
|
|
35
35
|
let _pixelDepth = 0;
|
|
36
36
|
let _refreshRate = 0;
|
|
37
37
|
|
|
38
|
+
// EnumDisplaySettings (current mode per \\.\DISPLAYn) - per-display refresh rate (issue #853)
|
|
39
|
+
const psCurrentModes =
|
|
40
|
+
"Add-Type -AssemblyName System.Windows.Forms; if (-not ('SiDevMode' -as [Type])) { Add-Type -TypeDefinition 'using System;using System.Runtime.InteropServices;[StructLayout(LayoutKind.Sequential,CharSet=CharSet.Ansi)]public struct SIDEVMODE{[MarshalAs(UnmanagedType.ByValTStr,SizeConst=32)]public string dmDeviceName;public short dmSpecVersion;public short dmDriverVersion;public short dmSize;public short dmDriverExtra;public int dmFields;public int dmPositionX;public int dmPositionY;public int dmDisplayOrientation;public int dmDisplayFixedOutput;public short dmColor;public short dmDuplex;public short dmYResolution;public short dmTTOption;public short dmCollate;[MarshalAs(UnmanagedType.ByValTStr,SizeConst=32)]public string dmFormName;public short dmLogPixels;public int dmBitsPerPel;public int dmPelsWidth;public int dmPelsHeight;public int dmDisplayFlags;public int dmDisplayFrequency;public int dmICMMethod;public int dmICMIntent;public int dmMediaType;public int dmDitherType;public int dmReserved1;public int dmReserved2;public int dmPanningWidth;public int dmPanningHeight;}public class SiDevMode{[DllImport(\"user32.dll\",CharSet=CharSet.Ansi)]public static extern bool EnumDisplaySettings(string lpszDeviceName,int iModeNum,ref SIDEVMODE lpDevMode);}' }; [System.Windows.Forms.Screen]::AllScreens | ForEach-Object { $dm = New-Object SIDEVMODE; $dm.dmSize = [System.Runtime.InteropServices.Marshal]::SizeOf($dm); if ([SiDevMode]::EnumDisplaySettings($_.DeviceName, -1, [ref]$dm)) { $_.DeviceName + '|' + $dm.dmDisplayFrequency + '|' + $dm.dmBitsPerPel + '|' + $dm.dmPelsWidth + '|' + $dm.dmPelsHeight } }";
|
|
41
|
+
|
|
38
42
|
const videoTypes = {
|
|
39
43
|
'-2': 'UNINITIALIZED',
|
|
40
44
|
'-1': 'OTHER',
|
|
@@ -53,7 +57,8 @@ const videoTypes = {
|
|
|
53
57
|
13: 'UDI embedded',
|
|
54
58
|
14: 'SDTVDONGLE',
|
|
55
59
|
15: 'MIRACAST',
|
|
56
|
-
2147483648: 'INTERNAL'
|
|
60
|
+
2147483648: 'INTERNAL',
|
|
61
|
+
4294967295: 'RDP'
|
|
57
62
|
};
|
|
58
63
|
|
|
59
64
|
function getVendorFromModel(model) {
|
|
@@ -78,7 +83,7 @@ function getVendorFromModel(model) {
|
|
|
78
83
|
{ pattern: 'APPLE.?', manufacturer: 'Apple' },
|
|
79
84
|
{ pattern: 'INTEL.?', manufacturer: 'Intel' },
|
|
80
85
|
{ pattern: 'AMD.?', manufacturer: 'AMD' },
|
|
81
|
-
{ pattern: 'NVIDIA.?', manufacturer: '
|
|
86
|
+
{ pattern: 'NVIDIA.?', manufacturer: 'NVIDIA' }
|
|
82
87
|
];
|
|
83
88
|
|
|
84
89
|
let result = '';
|
|
@@ -153,7 +158,7 @@ function graphics(callback) {
|
|
|
153
158
|
const bus = (item.sppci_bus || '').indexOf('builtin') > -1 ? 'Built-In' : (item.sppci_bus || '').indexOf('pcie') > -1 ? 'PCIe' : '';
|
|
154
159
|
const vram = (parseInt(item.spdisplays_vram || '', 10) || 0) * ((item.spdisplays_vram || '').indexOf('GB') > -1 ? 1024 : 1);
|
|
155
160
|
const vramDyn = (parseInt(item.spdisplays_vram_shared || '', 10) || 0) * ((item.spdisplays_vram_shared || '').indexOf('GB') > -1 ? 1024 : 1);
|
|
156
|
-
|
|
161
|
+
const metalVersion = getMetalVersion(item.spdisplays_metal || item.spdisplays_metalfamily || '');
|
|
157
162
|
res.controllers.push({
|
|
158
163
|
vendor: getVendorFromModel(item.spdisplays_vendor || '') || item.spdisplays_vendor || '',
|
|
159
164
|
model: item.sppci_model || '',
|
|
@@ -207,7 +212,7 @@ function graphics(callback) {
|
|
|
207
212
|
}
|
|
208
213
|
|
|
209
214
|
function parseLinesLinuxControllers(lines) {
|
|
210
|
-
|
|
215
|
+
const controllers = [];
|
|
211
216
|
let currentController = {
|
|
212
217
|
vendor: '',
|
|
213
218
|
subVendor: '',
|
|
@@ -243,14 +248,18 @@ function graphics(callback) {
|
|
|
243
248
|
if ('' !== line.trim()) {
|
|
244
249
|
if (' ' !== line[0] && '\t' !== line[0]) {
|
|
245
250
|
// first line of new entry
|
|
246
|
-
|
|
251
|
+
const isExternal = pciIDs.indexOf(line.split(' ')[0]) >= 0;
|
|
247
252
|
let vgapos = line.toLowerCase().indexOf(' vga ');
|
|
248
|
-
|
|
249
|
-
|
|
253
|
+
const _3dcontrollerpos = line.toLowerCase().indexOf('3d controller');
|
|
254
|
+
const _displaycontrollerpos = line.toLowerCase().indexOf('display controller');
|
|
255
|
+
if (vgapos !== -1 || _3dcontrollerpos !== -1 || _displaycontrollerpos !== -1) {
|
|
250
256
|
// VGA
|
|
251
257
|
if (_3dcontrollerpos !== -1 && vgapos === -1) {
|
|
252
258
|
vgapos = _3dcontrollerpos;
|
|
253
259
|
}
|
|
260
|
+
if (_displaycontrollerpos !== -1 && vgapos === -1) {
|
|
261
|
+
vgapos = _displaycontrollerpos;
|
|
262
|
+
}
|
|
254
263
|
if (currentController.vendor || currentController.model || currentController.bus || currentController.vram !== null || currentController.vramDynamic) {
|
|
255
264
|
// already a controller found
|
|
256
265
|
controllers.push(currentController);
|
|
@@ -269,8 +278,8 @@ function graphics(callback) {
|
|
|
269
278
|
currentController.busAddress = pciIDCandidate;
|
|
270
279
|
}
|
|
271
280
|
isGraphicsController = true;
|
|
272
|
-
|
|
273
|
-
|
|
281
|
+
const endpos = line.search(/\[[0-9a-f]{4}:[0-9a-f]{4}]|$/);
|
|
282
|
+
const parts = line.substr(vgapos, endpos - vgapos).split(':');
|
|
274
283
|
currentController.busAddress = line.substr(0, vgapos).trim();
|
|
275
284
|
if (parts.length > 1) {
|
|
276
285
|
parts[1] = parts[1].trim();
|
|
@@ -332,7 +341,7 @@ function graphics(callback) {
|
|
|
332
341
|
}
|
|
333
342
|
if (isGraphicsController) {
|
|
334
343
|
// within VGA details
|
|
335
|
-
|
|
344
|
+
const parts = line.split(':');
|
|
336
345
|
if (parts.length > 1 && parts[0].replace(/ +/g, '').toLowerCase().indexOf('devicename') !== -1 && parts[1].toLowerCase().indexOf('onboard') !== -1) {
|
|
337
346
|
currentController.bus = 'Onboard';
|
|
338
347
|
}
|
|
@@ -341,9 +350,13 @@ function graphics(callback) {
|
|
|
341
350
|
if (sizeMatch) {
|
|
342
351
|
let vram = parseInt(sizeMatch[1], 10);
|
|
343
352
|
const unit = (sizeMatch[2] || '').toUpperCase();
|
|
344
|
-
if (unit === 'G') {
|
|
345
|
-
|
|
346
|
-
else if (unit === '') {
|
|
353
|
+
if (unit === 'G') {
|
|
354
|
+
vram *= 1024;
|
|
355
|
+
} else if (unit === 'K') {
|
|
356
|
+
vram = Math.round(vram / 1024);
|
|
357
|
+
} else if (unit === '') {
|
|
358
|
+
vram = Math.round(vram / 1024 / 1024);
|
|
359
|
+
} // bytes
|
|
347
360
|
// keep the largest memory region (the actual framebuffer aperture)
|
|
348
361
|
if (currentController.vram === null || vram > currentController.vram) {
|
|
349
362
|
currentController.vram = vram;
|
|
@@ -374,7 +387,7 @@ function graphics(callback) {
|
|
|
374
387
|
}
|
|
375
388
|
return devices;
|
|
376
389
|
}, {});
|
|
377
|
-
for (
|
|
390
|
+
for (const deviceId in devices) {
|
|
378
391
|
const device = devices[deviceId];
|
|
379
392
|
if (device['CL_DEVICE_TYPE'] === 'CL_DEVICE_TYPE_GPU') {
|
|
380
393
|
let busAddress;
|
|
@@ -429,24 +442,29 @@ function graphics(callback) {
|
|
|
429
442
|
|
|
430
443
|
if (_windows) {
|
|
431
444
|
try {
|
|
432
|
-
const
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
.
|
|
437
|
-
.
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
445
|
+
const systemSmiPath = path.join(util.WINDIR, 'System32', 'nvidia-smi.exe');
|
|
446
|
+
if (fs.existsSync(systemSmiPath)) {
|
|
447
|
+
_nvidiaSmiPath = systemSmiPath;
|
|
448
|
+
} else {
|
|
449
|
+
const basePath = path.join(util.WINDIR, 'System32', 'DriverStore', 'FileRepository');
|
|
450
|
+
// find all directories that have an nvidia-smi.exe file with date
|
|
451
|
+
const candidates = fs
|
|
452
|
+
.readdirSync(basePath, { withFileTypes: true })
|
|
453
|
+
.filter((dir) => dir.isDirectory())
|
|
454
|
+
.map((dir) => {
|
|
455
|
+
const nvidiaSmiPath = path.join(basePath, dir.name, 'nvidia-smi.exe');
|
|
456
|
+
try {
|
|
457
|
+
const stats = fs.statSync(nvidiaSmiPath);
|
|
458
|
+
return { path: nvidiaSmiPath, ctime: stats.ctimeMs };
|
|
459
|
+
} catch {
|
|
460
|
+
return null;
|
|
461
|
+
}
|
|
462
|
+
})
|
|
463
|
+
.filter(Boolean);
|
|
464
|
+
if (candidates.length > 0) {
|
|
465
|
+
// take the most recent
|
|
466
|
+
_nvidiaSmiPath = candidates.reduce((prev, curr) => (curr.ctime > prev.ctime ? curr : prev)).path;
|
|
467
|
+
}
|
|
450
468
|
}
|
|
451
469
|
} catch {
|
|
452
470
|
util.noop();
|
|
@@ -459,7 +477,7 @@ function graphics(callback) {
|
|
|
459
477
|
|
|
460
478
|
function nvidiaSmi(options) {
|
|
461
479
|
const nvidiaSmiExe = getNvidiaSmi();
|
|
462
|
-
options = options || util.execOptsWin;
|
|
480
|
+
options = Object.assign({}, options || util.execOptsWin);
|
|
463
481
|
if (nvidiaSmiExe) {
|
|
464
482
|
const nvidiaSmiOpts =
|
|
465
483
|
'--query-gpu=driver_version,pci.sub_device_id,name,pci.bus_id,fan.speed,memory.total,memory.used,memory.free,utilization.gpu,utilization.memory,temperature.gpu,temperature.memory,power.draw,power.limit,clocks.gr,clocks.mem --format=csv,noheader,nounits';
|
|
@@ -669,11 +687,26 @@ function graphics(callback) {
|
|
|
669
687
|
let is_current = false;
|
|
670
688
|
let edid_raw = '';
|
|
671
689
|
let start = 0;
|
|
690
|
+
const applyEdid = () => {
|
|
691
|
+
const edid_decoded = parseLinesLinuxEdid(edid_raw);
|
|
692
|
+
currentDisplay.vendor = edid_decoded.vendor;
|
|
693
|
+
currentDisplay.model = edid_decoded.model;
|
|
694
|
+
currentDisplay.resolutionX = edid_decoded.resolutionX;
|
|
695
|
+
currentDisplay.resolutionY = edid_decoded.resolutionY;
|
|
696
|
+
currentDisplay.sizeX = edid_decoded.sizeX;
|
|
697
|
+
currentDisplay.sizeY = edid_decoded.sizeY;
|
|
698
|
+
currentDisplay.pixelDepth = depth;
|
|
699
|
+
is_edid = false;
|
|
700
|
+
};
|
|
672
701
|
for (let i = 1; i < lines.length; i++) {
|
|
673
702
|
// start with second line
|
|
674
703
|
if ('' !== lines[i].trim()) {
|
|
675
704
|
if (' ' !== lines[i][0] && '\t' !== lines[i][0] && lines[i].toLowerCase().indexOf(' connected ') !== -1) {
|
|
676
705
|
// first line of new entry
|
|
706
|
+
if (is_edid && edid_raw) {
|
|
707
|
+
// pending EDID belongs to the previous display
|
|
708
|
+
applyEdid();
|
|
709
|
+
}
|
|
677
710
|
if (
|
|
678
711
|
currentDisplay.model ||
|
|
679
712
|
currentDisplay.main ||
|
|
@@ -703,10 +736,15 @@ function graphics(callback) {
|
|
|
703
736
|
currentRefreshRate: null
|
|
704
737
|
};
|
|
705
738
|
}
|
|
706
|
-
|
|
739
|
+
const parts = lines[i].split(' ');
|
|
707
740
|
currentDisplay.connection = parts[0];
|
|
708
741
|
currentDisplay.main = lines[i].toLowerCase().indexOf(' primary ') >= 0;
|
|
709
742
|
currentDisplay.builtin = parts[0].toLowerCase().indexOf('edp') >= 0;
|
|
743
|
+
const geometry = lines[i].match(/\d+x\d+\+(-?\d+)\+(-?\d+)/);
|
|
744
|
+
if (geometry) {
|
|
745
|
+
currentDisplay.positionX = util.toInt(geometry[1]);
|
|
746
|
+
currentDisplay.positionY = util.toInt(geometry[2]);
|
|
747
|
+
}
|
|
710
748
|
}
|
|
711
749
|
|
|
712
750
|
// try to read EDID information
|
|
@@ -715,19 +753,12 @@ function graphics(callback) {
|
|
|
715
753
|
edid_raw += lines[i].toLowerCase().trim();
|
|
716
754
|
} else {
|
|
717
755
|
// parsen EDID
|
|
718
|
-
|
|
719
|
-
currentDisplay.vendor = edid_decoded.vendor;
|
|
720
|
-
currentDisplay.model = edid_decoded.model;
|
|
721
|
-
currentDisplay.resolutionX = edid_decoded.resolutionX;
|
|
722
|
-
currentDisplay.resolutionY = edid_decoded.resolutionY;
|
|
723
|
-
currentDisplay.sizeX = edid_decoded.sizeX;
|
|
724
|
-
currentDisplay.sizeY = edid_decoded.sizeY;
|
|
725
|
-
currentDisplay.pixelDepth = depth;
|
|
726
|
-
is_edid = false;
|
|
756
|
+
applyEdid();
|
|
727
757
|
}
|
|
728
758
|
}
|
|
729
759
|
if (lines[i].toLowerCase().indexOf('edid:') >= 0) {
|
|
730
760
|
is_edid = true;
|
|
761
|
+
edid_raw = '';
|
|
731
762
|
start = lines[i].search(/\S|$/);
|
|
732
763
|
}
|
|
733
764
|
if (lines[i].toLowerCase().indexOf('*current') >= 0) {
|
|
@@ -750,6 +781,10 @@ function graphics(callback) {
|
|
|
750
781
|
}
|
|
751
782
|
|
|
752
783
|
// pushen displays
|
|
784
|
+
if (is_edid && edid_raw) {
|
|
785
|
+
// EDID was the last block in the output
|
|
786
|
+
applyEdid();
|
|
787
|
+
}
|
|
753
788
|
if (
|
|
754
789
|
currentDisplay.model ||
|
|
755
790
|
currentDisplay.main ||
|
|
@@ -782,6 +817,20 @@ function graphics(callback) {
|
|
|
782
817
|
} catch (e) {
|
|
783
818
|
util.noop();
|
|
784
819
|
}
|
|
820
|
+
try {
|
|
821
|
+
// GPU temperature (Apple Silicon) - optional dependency
|
|
822
|
+
const macosTemp = require('macos-temperature-sensor');
|
|
823
|
+
const temps = macosTemp.temperature();
|
|
824
|
+
if (temps && temps.gpu) {
|
|
825
|
+
result.controllers.forEach((controller) => {
|
|
826
|
+
if (controller.bus === 'Built-In') {
|
|
827
|
+
controller.temperatureGpu = Math.round(temps.gpu * 100) / 100;
|
|
828
|
+
}
|
|
829
|
+
});
|
|
830
|
+
}
|
|
831
|
+
} catch {
|
|
832
|
+
util.noop();
|
|
833
|
+
}
|
|
785
834
|
try {
|
|
786
835
|
stdout = execSync(
|
|
787
836
|
'defaults read /Library/Preferences/com.apple.windowserver.plist 2>/dev/null;defaults read /Library/Preferences/com.apple.windowserver.displays.plist 2>/dev/null; echo ""',
|
|
@@ -834,7 +883,7 @@ function graphics(callback) {
|
|
|
834
883
|
const cmd = "fbset -s 2> /dev/null | grep 'mode \"' ; vcgencmd get_mem gpu 2> /dev/null; tvservice -s 2> /dev/null; tvservice -n 2> /dev/null;";
|
|
835
884
|
exec(cmd, (error, stdout) => {
|
|
836
885
|
const lines = stdout.toString().split('\n');
|
|
837
|
-
if (lines.length > 3 && lines[0].indexOf('mode "') >=
|
|
886
|
+
if (lines.length > 3 && lines[0].indexOf('mode "') >= 0 && lines[2].indexOf('0x12000a') > -1) {
|
|
838
887
|
const parts = lines[0].replace('mode', '').replace(/"/g, '').trim().split('x');
|
|
839
888
|
if (parts.length === 2) {
|
|
840
889
|
result.displays.push({
|
|
@@ -856,12 +905,12 @@ function graphics(callback) {
|
|
|
856
905
|
});
|
|
857
906
|
}
|
|
858
907
|
}
|
|
859
|
-
if (lines.length >= 1 && stdout.toString().indexOf('gpu=') >=
|
|
908
|
+
if (lines.length >= 1 && stdout.toString().indexOf('gpu=') >= 0) {
|
|
860
909
|
result.controllers.push({
|
|
861
910
|
vendor: 'Broadcom',
|
|
862
911
|
model: util.getRpiGpu(),
|
|
863
912
|
bus: '',
|
|
864
|
-
vram: util.getValue(lines, 'gpu', '=').replace('M', ''),
|
|
913
|
+
vram: parseInt(util.getValue(lines, 'gpu', '=').replace('M', ''), 10) || null,
|
|
865
914
|
vramDynamic: true
|
|
866
915
|
});
|
|
867
916
|
}
|
|
@@ -879,7 +928,7 @@ function graphics(callback) {
|
|
|
879
928
|
// needs to be rewritten ... using no spread operators
|
|
880
929
|
result.controllers = result.controllers.map((controller) => {
|
|
881
930
|
// match by busAddress
|
|
882
|
-
return mergeControllerNvidia(controller, nvidiaData.find((contr) => contr.pciBus.toLowerCase().endsWith(controller.busAddress.toLowerCase())) || {});
|
|
931
|
+
return mergeControllerNvidia(controller, nvidiaData.find((contr) => contr.pciBus && controller.busAddress && contr.pciBus.toLowerCase().endsWith(controller.busAddress.toLowerCase())) || {});
|
|
883
932
|
});
|
|
884
933
|
}
|
|
885
934
|
}
|
|
@@ -941,9 +990,10 @@ function graphics(callback) {
|
|
|
941
990
|
workload.push(util.powerShell('Get-CimInstance -Namespace root\\wmi -ClassName WmiMonitorConnectionParams | fl'));
|
|
942
991
|
workload.push(
|
|
943
992
|
util.powerShell(
|
|
944
|
-
'gwmi WmiMonitorID -Namespace root\\wmi | ForEach-Object {(($_.ManufacturerName -notmatch 0 | foreach {[char]$_}) -join "") + "|" + (($_.ProductCodeID -notmatch 0 | foreach {[char]$_}) -join "") + "|" + (($_.UserFriendlyName -notmatch 0 | foreach {[char]$_}) -join "") + "|" + (($_.SerialNumberID -notmatch 0 | foreach {[char]$_}) -join "") + "|" + $_.InstanceName}'
|
|
993
|
+
'gwmi WmiMonitorID -Namespace root\\wmi | ForEach-Object {(($_.ManufacturerName -notmatch 0 | foreach {[char]$_}) -join "") + "|" + (($_.ProductCodeID -notmatch 0 | foreach {[char]$_}) -join "") + "|" + (($_.UserFriendlyName -notmatch 0 | foreach {[char]$_}) -join "") + "|" + (($_.SerialNumberID -notmatch 0 | foreach {[char]$_}) -join "") + "|" + $_.YearOfManufacture + "|" + $_.InstanceName}'
|
|
945
994
|
)
|
|
946
995
|
);
|
|
996
|
+
workload.push(util.powerShell(psCurrentModes));
|
|
947
997
|
|
|
948
998
|
const nvidiaData = nvidiaDevices();
|
|
949
999
|
|
|
@@ -960,7 +1010,7 @@ function graphics(callback) {
|
|
|
960
1010
|
controller,
|
|
961
1011
|
nvidiaData.find((device) => {
|
|
962
1012
|
let windowsSubDeviceId = (controller.subDeviceId || '').toLowerCase();
|
|
963
|
-
const nvidiaSubDeviceIdParts = device.subDeviceId.split('x');
|
|
1013
|
+
const nvidiaSubDeviceIdParts = (device.subDeviceId || '').split('x');
|
|
964
1014
|
let nvidiaSubDeviceId = nvidiaSubDeviceIdParts.length > 1 ? nvidiaSubDeviceIdParts[1].toLowerCase() : nvidiaSubDeviceIdParts[0].toLowerCase();
|
|
965
1015
|
const lengthDifference = Math.abs(windowsSubDeviceId.length - nvidiaSubDeviceId.length);
|
|
966
1016
|
if (windowsSubDeviceId.length > nvidiaSubDeviceId.length) {
|
|
@@ -990,35 +1040,65 @@ function graphics(callback) {
|
|
|
990
1040
|
dsections.pop();
|
|
991
1041
|
}
|
|
992
1042
|
|
|
993
|
-
//
|
|
994
|
-
|
|
995
|
-
|
|
1043
|
+
// physical monitors (powershell) - keyed by InstanceName (issue #764)
|
|
1044
|
+
// inactive monitors (attached but not part of the desktop, e.g. "PC screen only") are skipped
|
|
1045
|
+
const monitors = [];
|
|
1046
|
+
data[3].replace(/\r/g, '').split(/\n\s*\n/).forEach((section) => {
|
|
1047
|
+
const lines = section.split('\n');
|
|
1048
|
+
const monitorInstanceName = util.getValue(lines, 'InstanceName').toLowerCase();
|
|
1049
|
+
const monitorActive = util.getValue(lines, 'Active').toLowerCase() !== 'false';
|
|
1050
|
+
if (monitorInstanceName && monitorActive) {
|
|
1051
|
+
monitors.push({
|
|
1052
|
+
instanceName: monitorInstanceName,
|
|
1053
|
+
sizeX: util.getValue(lines, 'MaxHorizontalImageSize'),
|
|
1054
|
+
sizeY: util.getValue(lines, 'MaxVerticalImageSize')
|
|
1055
|
+
});
|
|
1056
|
+
}
|
|
1057
|
+
});
|
|
996
1058
|
|
|
997
1059
|
// forms.screens (powershell)
|
|
998
1060
|
const ssections = data[4].replace(/\r/g, '').split('BitsPerPixel ');
|
|
999
1061
|
ssections.shift();
|
|
1000
1062
|
|
|
1001
|
-
// connection params (powershell) - video type
|
|
1002
|
-
const
|
|
1003
|
-
|
|
1063
|
+
// connection params (powershell) - video type per InstanceName (issue #764)
|
|
1064
|
+
const connections = Object.create(null);
|
|
1065
|
+
data[5].replace(/\r/g, '').split(/\n\s*\n/).forEach((section) => {
|
|
1066
|
+
const lines = section.split('\n');
|
|
1067
|
+
const connectionInstanceName = util.getValue(lines, 'InstanceName').toLowerCase();
|
|
1068
|
+
if (connectionInstanceName) {
|
|
1069
|
+
connections[connectionInstanceName] = util.getValue(lines, 'VideoOutputTechnology');
|
|
1070
|
+
}
|
|
1071
|
+
});
|
|
1004
1072
|
|
|
1005
1073
|
// monitor ID (powershell) - model / vendor
|
|
1006
1074
|
const res = data[6].replace(/\r/g, '').split(/\n/);
|
|
1007
1075
|
const isections = [];
|
|
1008
1076
|
res.forEach((element) => {
|
|
1009
1077
|
const parts = element.split('|');
|
|
1010
|
-
if (parts.length ===
|
|
1078
|
+
if (parts.length === 6) {
|
|
1011
1079
|
isections.push({
|
|
1012
1080
|
vendor: parts[0],
|
|
1013
1081
|
code: parts[1],
|
|
1014
1082
|
model: parts[2],
|
|
1015
1083
|
serial: parts[3],
|
|
1016
|
-
|
|
1084
|
+
productionYear: util.toInt(parts[4]) || null,
|
|
1085
|
+
instanceId: parts[5]
|
|
1017
1086
|
});
|
|
1018
1087
|
}
|
|
1019
1088
|
});
|
|
1020
1089
|
|
|
1021
|
-
|
|
1090
|
+
// current display mode per device name (issue #853)
|
|
1091
|
+
const currentModes = Object.create(null);
|
|
1092
|
+
(data[7] || '').replace(/\r/g, '').split(/\n/).forEach((element) => {
|
|
1093
|
+
const parts = element.split('|');
|
|
1094
|
+
const frequency = parts.length === 5 ? util.toInt(parts[1]) : 0;
|
|
1095
|
+
// dmDisplayFrequency 0/1 means hardware default
|
|
1096
|
+
if (frequency > 1 && parts[0]) {
|
|
1097
|
+
currentModes[parts[0].trim().toLowerCase()] = frequency;
|
|
1098
|
+
}
|
|
1099
|
+
});
|
|
1100
|
+
|
|
1101
|
+
result.displays = parseLinesWindowsDisplaysPowershell(ssections, monitors, dsections, connections, isections, currentModes);
|
|
1022
1102
|
|
|
1023
1103
|
if (result.displays.length === 1) {
|
|
1024
1104
|
if (_resolutionX) {
|
|
@@ -1157,7 +1237,7 @@ function graphics(callback) {
|
|
|
1157
1237
|
return controllers;
|
|
1158
1238
|
}
|
|
1159
1239
|
|
|
1160
|
-
function parseLinesWindowsDisplaysPowershell(ssections,
|
|
1240
|
+
function parseLinesWindowsDisplaysPowershell(ssections, monitors, dsections, connections, isections, currentModes) {
|
|
1161
1241
|
const displays = [];
|
|
1162
1242
|
let vendor = '';
|
|
1163
1243
|
let model = '';
|
|
@@ -1172,40 +1252,34 @@ function graphics(callback) {
|
|
|
1172
1252
|
resolutionX = util.toInt(util.getValue(linesDisplay, 'ScreenWidth', ':'));
|
|
1173
1253
|
resolutionY = util.toInt(util.getValue(linesDisplay, 'ScreenHeight', ':'));
|
|
1174
1254
|
}
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
const
|
|
1185
|
-
const
|
|
1186
|
-
|
|
1187
|
-
const linesConnection = tsections[i].split('\n');
|
|
1188
|
-
const bitsPerPixel = util.getValue(linesScreen, 'BitsPerPixel');
|
|
1255
|
+
// iterate over physical monitors too - mirrored monitors have no own logical screen (issue #940)
|
|
1256
|
+
const count = Math.max(ssections.length, monitors.length);
|
|
1257
|
+
for (let i = 0; i < count; i++) {
|
|
1258
|
+
const hasOwnScreen = i < ssections.length;
|
|
1259
|
+
// mirrored monitors show the same image as the first screen
|
|
1260
|
+
const ssection = hasOwnScreen ? ssections[i] : ssections[0];
|
|
1261
|
+
if (ssection !== undefined && ssection.trim() !== '') {
|
|
1262
|
+
const linesScreen = ('BitsPerPixel ' + ssection).split('\n');
|
|
1263
|
+
// screen <-> monitor correlation stays index based - Forms.Screen exposes no shared key with root\wmi
|
|
1264
|
+
const monitor = monitors[i];
|
|
1265
|
+
const instanceName = monitor ? monitor.instanceName : '';
|
|
1266
|
+
const bitsPerPixel = util.toInt(util.getValue(linesScreen, 'BitsPerPixel')) || null;
|
|
1189
1267
|
const bounds = util.getValue(linesScreen, 'Bounds').replace('{', '').replace('}', '').replace(/=/g, ':').split(',');
|
|
1190
1268
|
const primary = util.getValue(linesScreen, 'Primary');
|
|
1191
|
-
const sizeX =
|
|
1192
|
-
const sizeY =
|
|
1193
|
-
const
|
|
1194
|
-
const videoOutputTechnology = util.getValue(linesConnection, 'VideoOutputTechnology');
|
|
1269
|
+
const sizeX = monitor ? monitor.sizeX : '';
|
|
1270
|
+
const sizeY = monitor ? monitor.sizeY : '';
|
|
1271
|
+
const videoOutputTechnology = instanceName && connections[instanceName] !== undefined ? connections[instanceName] : '';
|
|
1195
1272
|
const deviceName = util.getValue(linesScreen, 'DeviceName');
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
isections.forEach((element) => {
|
|
1199
|
-
if (element.instanceId.toLowerCase().startsWith(instanceName) && vendor.startsWith('(') && model.startsWith('PnP')) {
|
|
1200
|
-
displayVendor = element.vendor;
|
|
1201
|
-
displayModel = element.model;
|
|
1202
|
-
}
|
|
1203
|
-
});
|
|
1273
|
+
// WmiMonitorID data matches per InstanceName - prefer it over the locale-dependent Win32_DesktopMonitor values
|
|
1274
|
+
const isection = instanceName ? isections.find((element) => element.instanceId.toLowerCase().startsWith(instanceName)) : undefined;
|
|
1204
1275
|
displays.push({
|
|
1205
|
-
vendor: instanceName.startsWith(deviceID)
|
|
1206
|
-
model: instanceName.startsWith(deviceID)
|
|
1276
|
+
vendor: (isection && isection.vendor) || (instanceName.startsWith(deviceID) ? vendor : ''),
|
|
1277
|
+
model: (isection && isection.model) || (instanceName.startsWith(deviceID) ? model : ''),
|
|
1278
|
+
serial: (isection && isection.serial) || null,
|
|
1279
|
+
productionYear: isection ? isection.productionYear : null,
|
|
1280
|
+
displayId: instanceName || null,
|
|
1207
1281
|
deviceName,
|
|
1208
|
-
main: primary.toLowerCase() === 'true',
|
|
1282
|
+
main: hasOwnScreen ? primary.toLowerCase() === 'true' : false,
|
|
1209
1283
|
builtin: videoOutputTechnology === '2147483648',
|
|
1210
1284
|
connection: videoOutputTechnology && videoTypes[videoOutputTechnology] ? videoTypes[videoOutputTechnology] : '',
|
|
1211
1285
|
resolutionX: util.toInt(util.getValue(bounds, 'Width', ':')),
|
|
@@ -1216,7 +1290,8 @@ function graphics(callback) {
|
|
|
1216
1290
|
currentResX: util.toInt(util.getValue(bounds, 'Width', ':')),
|
|
1217
1291
|
currentResY: util.toInt(util.getValue(bounds, 'Height', ':')),
|
|
1218
1292
|
positionX: util.toInt(util.getValue(bounds, 'X', ':')),
|
|
1219
|
-
positionY: util.toInt(util.getValue(bounds, 'Y', ':'))
|
|
1293
|
+
positionY: util.toInt(util.getValue(bounds, 'Y', ':')),
|
|
1294
|
+
currentRefreshRate: currentModes[deviceName.toLowerCase()] || null
|
|
1220
1295
|
});
|
|
1221
1296
|
}
|
|
1222
1297
|
}
|
|
@@ -1224,6 +1299,9 @@ function graphics(callback) {
|
|
|
1224
1299
|
displays.push({
|
|
1225
1300
|
vendor,
|
|
1226
1301
|
model,
|
|
1302
|
+
serial: null,
|
|
1303
|
+
productionYear: null,
|
|
1304
|
+
displayId: null,
|
|
1227
1305
|
main: true,
|
|
1228
1306
|
sizeX: null,
|
|
1229
1307
|
sizeY: null,
|
package/lib/index.d.ts
CHANGED
package/lib/index.js
CHANGED
|
@@ -325,8 +325,10 @@ function getAllData(srv, iface, callback) {
|
|
|
325
325
|
function get(valueObject, callback) {
|
|
326
326
|
return new Promise((resolve) => {
|
|
327
327
|
process.nextTick(() => {
|
|
328
|
+
const blocked = ['get', 'getStaticData', 'getDynamicData', 'getAllData', 'observe', 'powerShellStart', 'powerShellRelease'];
|
|
329
|
+
const isGettable = (key) => ({}).hasOwnProperty.call(exports, key) && typeof exports[key] === 'function' && typeof valueObject[key] === 'string' && blocked.indexOf(key) < 0;
|
|
328
330
|
const allPromises = Object.keys(valueObject)
|
|
329
|
-
.filter((func) => (
|
|
331
|
+
.filter((func) => isGettable(func))
|
|
330
332
|
.map((func) => {
|
|
331
333
|
const params = valueObject[func].substring(valueObject[func].lastIndexOf('(') + 1, valueObject[func].lastIndexOf(')'));
|
|
332
334
|
let funcWithoutParams = func.indexOf(')') >= 0 ? func.split(')')[1].trim() : func;
|
|
@@ -342,7 +344,7 @@ function get(valueObject, callback) {
|
|
|
342
344
|
const result = {};
|
|
343
345
|
let i = 0;
|
|
344
346
|
for (let key in valueObject) {
|
|
345
|
-
if ({}.hasOwnProperty.call(valueObject, key) &&
|
|
347
|
+
if ({}.hasOwnProperty.call(valueObject, key) && isGettable(key) && data.length > i) {
|
|
346
348
|
if (valueObject[key] === '*' || valueObject[key] === 'all') {
|
|
347
349
|
result[key] = data[i];
|
|
348
350
|
} else {
|
package/lib/memory.js
CHANGED
|
@@ -401,6 +401,7 @@ function memLayout(callback) {
|
|
|
401
401
|
ecc: null,
|
|
402
402
|
clockSpeed: 0,
|
|
403
403
|
formFactor: util.getValue(lines, 'Form Factor:'),
|
|
404
|
+
manufacturer: '',
|
|
404
405
|
partNum: '',
|
|
405
406
|
serialNum: '',
|
|
406
407
|
voltageConfigured: null,
|
|
@@ -490,10 +491,12 @@ function memLayout(callback) {
|
|
|
490
491
|
devices.forEach((device) => {
|
|
491
492
|
const lines = device.split('\n');
|
|
492
493
|
const bank = (hasBank ? 'BANK ' : 'DIMM') + lines[0].trim().split('/')[0];
|
|
493
|
-
const
|
|
494
|
+
const sizeString = util.getValue(lines, ' Size');
|
|
495
|
+
const size = parseInt(sizeString);
|
|
496
|
+
const sizeUnit = sizeString.toLowerCase().indexOf('mb') >= 0 ? 1024 * 1024 : sizeString.toLowerCase().indexOf('tb') >= 0 ? 1024 * 1024 * 1024 * 1024 : 1024 * 1024 * 1024;
|
|
494
497
|
if (size) {
|
|
495
498
|
result.push({
|
|
496
|
-
size: size *
|
|
499
|
+
size: size * sizeUnit,
|
|
497
500
|
bank: bank,
|
|
498
501
|
type: util.getValue(lines, ' Type:'),
|
|
499
502
|
ecc: eccStatus ? eccStatus === 'enabled' : null,
|
|
@@ -586,7 +589,7 @@ function memLayout(callback) {
|
|
|
586
589
|
result.push({
|
|
587
590
|
size,
|
|
588
591
|
bank: util.getValue(lines, 'BankLabel', ':') + (tagInt[1] ? '/' + tagInt[1] : ''), // BankLabel
|
|
589
|
-
type: memoryTypes[parseInt(util.getValue(lines, 'MemoryType', ':'), 10) || parseInt(util.getValue(lines, 'SMBIOSMemoryType', ':'), 10)],
|
|
592
|
+
type: memoryTypes[parseInt(util.getValue(lines, 'MemoryType', ':'), 10) || parseInt(util.getValue(lines, 'SMBIOSMemoryType', ':'), 10) || 0],
|
|
590
593
|
ecc: dataWidth && totalWidth ? totalWidth > dataWidth : false,
|
|
591
594
|
clockSpeed: parseInt(util.getValue(lines, 'ConfiguredClockSpeed', ':'), 10) || parseInt(util.getValue(lines, 'Speed', ':'), 10) || 0,
|
|
592
595
|
formFactor: FormFactors[parseInt(util.getValue(lines, 'FormFactor', ':'), 10) || 0],
|
package/lib/network.js
CHANGED
|
@@ -546,8 +546,12 @@ function getLinuxIfaceConnectionName(interfaceName) {
|
|
|
546
546
|
}
|
|
547
547
|
}
|
|
548
548
|
|
|
549
|
-
function checkLinuxDCHPInterfaces(file) {
|
|
549
|
+
function checkLinuxDCHPInterfaces(file, depth) {
|
|
550
550
|
let result = [];
|
|
551
|
+
depth = depth || 0;
|
|
552
|
+
if (depth > 10) {
|
|
553
|
+
return result;
|
|
554
|
+
}
|
|
551
555
|
try {
|
|
552
556
|
const content = readFileSync(file, { encoding: 'utf8' });
|
|
553
557
|
const lines = content.split('\n').filter((l) => /iface|source/.test(l));
|
|
@@ -561,7 +565,7 @@ function checkLinuxDCHPInterfaces(file) {
|
|
|
561
565
|
}
|
|
562
566
|
if (line.toLowerCase().includes('source')) {
|
|
563
567
|
const file = line.split(' ')[1];
|
|
564
|
-
result = result.concat(checkLinuxDCHPInterfaces(file));
|
|
568
|
+
result = result.concat(checkLinuxDCHPInterfaces(file, depth + 1));
|
|
565
569
|
}
|
|
566
570
|
});
|
|
567
571
|
} catch {
|
|
@@ -1426,7 +1430,7 @@ function networkStatsSingle(iface) {
|
|
|
1426
1430
|
rx_errors = rx_errors + parseInt(line[5]);
|
|
1427
1431
|
}
|
|
1428
1432
|
tx_bytes = tx_bytes + parseInt(line[10]);
|
|
1429
|
-
if (line[12].trim() !== '-') {
|
|
1433
|
+
if (line[12] && line[12].trim() !== '-') {
|
|
1430
1434
|
tx_dropped = tx_dropped + parseInt(line[12]);
|
|
1431
1435
|
}
|
|
1432
1436
|
if (line[9].trim() !== '-') {
|
|
@@ -1725,10 +1729,10 @@ function networkConnections(callback) {
|
|
|
1725
1729
|
const hasState = states.indexOf(line[5]) >= 0;
|
|
1726
1730
|
const connstate = hasState ? line[5] : 'UNKNOWN';
|
|
1727
1731
|
let pidField = '';
|
|
1728
|
-
if (line[line.length - 9].indexOf(':') >= 0) {
|
|
1732
|
+
if (line[line.length - 9] && line[line.length - 9].indexOf(':') >= 0) {
|
|
1729
1733
|
pidField = line[line.length - 9].split(':')[1];
|
|
1730
1734
|
} else {
|
|
1731
|
-
pidField = line[pidPos + (hasState ? 0 : -1)];
|
|
1735
|
+
pidField = line[pidPos + (hasState ? 0 : -1)] || '';
|
|
1732
1736
|
|
|
1733
1737
|
if (pidField.indexOf(':') >= 0) {
|
|
1734
1738
|
pidField = pidField.split(':')[1];
|
|
@@ -1754,6 +1758,11 @@ function networkConnections(callback) {
|
|
|
1754
1758
|
}
|
|
1755
1759
|
resolve(result);
|
|
1756
1760
|
});
|
|
1761
|
+
} else {
|
|
1762
|
+
if (callback) {
|
|
1763
|
+
callback(result);
|
|
1764
|
+
}
|
|
1765
|
+
resolve(result);
|
|
1757
1766
|
}
|
|
1758
1767
|
});
|
|
1759
1768
|
}
|
|
@@ -1844,6 +1853,11 @@ function networkConnections(callback) {
|
|
|
1844
1853
|
callback(result);
|
|
1845
1854
|
}
|
|
1846
1855
|
resolve(result);
|
|
1856
|
+
} else {
|
|
1857
|
+
if (callback) {
|
|
1858
|
+
callback(result);
|
|
1859
|
+
}
|
|
1860
|
+
resolve(result);
|
|
1847
1861
|
}
|
|
1848
1862
|
});
|
|
1849
1863
|
} catch {
|