systeminformation 5.31.17 → 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/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: 'NVDIA' }
86
+ { pattern: 'NVIDIA.?', manufacturer: 'NVIDIA' }
82
87
  ];
83
88
 
84
89
  let result = '';
@@ -246,11 +251,15 @@ function graphics(callback) {
246
251
  const isExternal = pciIDs.indexOf(line.split(' ')[0]) >= 0;
247
252
  let vgapos = line.toLowerCase().indexOf(' vga ');
248
253
  const _3dcontrollerpos = line.toLowerCase().indexOf('3d controller');
249
- if (vgapos !== -1 || _3dcontrollerpos !== -1) {
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);
@@ -468,7 +477,7 @@ function graphics(callback) {
468
477
 
469
478
  function nvidiaSmi(options) {
470
479
  const nvidiaSmiExe = getNvidiaSmi();
471
- options = options || util.execOptsWin;
480
+ options = Object.assign({}, options || util.execOptsWin);
472
481
  if (nvidiaSmiExe) {
473
482
  const nvidiaSmiOpts =
474
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';
@@ -678,11 +687,26 @@ function graphics(callback) {
678
687
  let is_current = false;
679
688
  let edid_raw = '';
680
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
+ };
681
701
  for (let i = 1; i < lines.length; i++) {
682
702
  // start with second line
683
703
  if ('' !== lines[i].trim()) {
684
704
  if (' ' !== lines[i][0] && '\t' !== lines[i][0] && lines[i].toLowerCase().indexOf(' connected ') !== -1) {
685
705
  // first line of new entry
706
+ if (is_edid && edid_raw) {
707
+ // pending EDID belongs to the previous display
708
+ applyEdid();
709
+ }
686
710
  if (
687
711
  currentDisplay.model ||
688
712
  currentDisplay.main ||
@@ -716,6 +740,11 @@ function graphics(callback) {
716
740
  currentDisplay.connection = parts[0];
717
741
  currentDisplay.main = lines[i].toLowerCase().indexOf(' primary ') >= 0;
718
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
+ }
719
748
  }
720
749
 
721
750
  // try to read EDID information
@@ -724,19 +753,12 @@ function graphics(callback) {
724
753
  edid_raw += lines[i].toLowerCase().trim();
725
754
  } else {
726
755
  // parsen EDID
727
- const edid_decoded = parseLinesLinuxEdid(edid_raw);
728
- currentDisplay.vendor = edid_decoded.vendor;
729
- currentDisplay.model = edid_decoded.model;
730
- currentDisplay.resolutionX = edid_decoded.resolutionX;
731
- currentDisplay.resolutionY = edid_decoded.resolutionY;
732
- currentDisplay.sizeX = edid_decoded.sizeX;
733
- currentDisplay.sizeY = edid_decoded.sizeY;
734
- currentDisplay.pixelDepth = depth;
735
- is_edid = false;
756
+ applyEdid();
736
757
  }
737
758
  }
738
759
  if (lines[i].toLowerCase().indexOf('edid:') >= 0) {
739
760
  is_edid = true;
761
+ edid_raw = '';
740
762
  start = lines[i].search(/\S|$/);
741
763
  }
742
764
  if (lines[i].toLowerCase().indexOf('*current') >= 0) {
@@ -759,6 +781,10 @@ function graphics(callback) {
759
781
  }
760
782
 
761
783
  // pushen displays
784
+ if (is_edid && edid_raw) {
785
+ // EDID was the last block in the output
786
+ applyEdid();
787
+ }
762
788
  if (
763
789
  currentDisplay.model ||
764
790
  currentDisplay.main ||
@@ -791,6 +817,20 @@ function graphics(callback) {
791
817
  } catch (e) {
792
818
  util.noop();
793
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
+ }
794
834
  try {
795
835
  stdout = execSync(
796
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 ""',
@@ -843,7 +883,7 @@ function graphics(callback) {
843
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;";
844
884
  exec(cmd, (error, stdout) => {
845
885
  const lines = stdout.toString().split('\n');
846
- if (lines.length > 3 && lines[0].indexOf('mode "') >= -1 && lines[2].indexOf('0x12000a') > -1) {
886
+ if (lines.length > 3 && lines[0].indexOf('mode "') >= 0 && lines[2].indexOf('0x12000a') > -1) {
847
887
  const parts = lines[0].replace('mode', '').replace(/"/g, '').trim().split('x');
848
888
  if (parts.length === 2) {
849
889
  result.displays.push({
@@ -865,12 +905,12 @@ function graphics(callback) {
865
905
  });
866
906
  }
867
907
  }
868
- if (lines.length >= 1 && stdout.toString().indexOf('gpu=') >= -1) {
908
+ if (lines.length >= 1 && stdout.toString().indexOf('gpu=') >= 0) {
869
909
  result.controllers.push({
870
910
  vendor: 'Broadcom',
871
911
  model: util.getRpiGpu(),
872
912
  bus: '',
873
- vram: util.getValue(lines, 'gpu', '=').replace('M', ''),
913
+ vram: parseInt(util.getValue(lines, 'gpu', '=').replace('M', ''), 10) || null,
874
914
  vramDynamic: true
875
915
  });
876
916
  }
@@ -888,7 +928,7 @@ function graphics(callback) {
888
928
  // needs to be rewritten ... using no spread operators
889
929
  result.controllers = result.controllers.map((controller) => {
890
930
  // match by busAddress
891
- 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())) || {});
892
932
  });
893
933
  }
894
934
  }
@@ -950,9 +990,10 @@ function graphics(callback) {
950
990
  workload.push(util.powerShell('Get-CimInstance -Namespace root\\wmi -ClassName WmiMonitorConnectionParams | fl'));
951
991
  workload.push(
952
992
  util.powerShell(
953
- '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}'
954
994
  )
955
995
  );
996
+ workload.push(util.powerShell(psCurrentModes));
956
997
 
957
998
  const nvidiaData = nvidiaDevices();
958
999
 
@@ -969,7 +1010,7 @@ function graphics(callback) {
969
1010
  controller,
970
1011
  nvidiaData.find((device) => {
971
1012
  let windowsSubDeviceId = (controller.subDeviceId || '').toLowerCase();
972
- const nvidiaSubDeviceIdParts = device.subDeviceId.split('x');
1013
+ const nvidiaSubDeviceIdParts = (device.subDeviceId || '').split('x');
973
1014
  let nvidiaSubDeviceId = nvidiaSubDeviceIdParts.length > 1 ? nvidiaSubDeviceIdParts[1].toLowerCase() : nvidiaSubDeviceIdParts[0].toLowerCase();
974
1015
  const lengthDifference = Math.abs(windowsSubDeviceId.length - nvidiaSubDeviceId.length);
975
1016
  if (windowsSubDeviceId.length > nvidiaSubDeviceId.length) {
@@ -999,35 +1040,65 @@ function graphics(callback) {
999
1040
  dsections.pop();
1000
1041
  }
1001
1042
 
1002
- // monitor (powershell)
1003
- const msections = data[3].replace(/\r/g, '').split('Active ');
1004
- msections.shift();
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
+ });
1005
1058
 
1006
1059
  // forms.screens (powershell)
1007
1060
  const ssections = data[4].replace(/\r/g, '').split('BitsPerPixel ');
1008
1061
  ssections.shift();
1009
1062
 
1010
- // connection params (powershell) - video type
1011
- const tsections = data[5].replace(/\r/g, '').split(/\n\s*\n/);
1012
- tsections.shift();
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
+ });
1013
1072
 
1014
1073
  // monitor ID (powershell) - model / vendor
1015
1074
  const res = data[6].replace(/\r/g, '').split(/\n/);
1016
1075
  const isections = [];
1017
1076
  res.forEach((element) => {
1018
1077
  const parts = element.split('|');
1019
- if (parts.length === 5) {
1078
+ if (parts.length === 6) {
1020
1079
  isections.push({
1021
1080
  vendor: parts[0],
1022
1081
  code: parts[1],
1023
1082
  model: parts[2],
1024
1083
  serial: parts[3],
1025
- instanceId: parts[4]
1084
+ productionYear: util.toInt(parts[4]) || null,
1085
+ instanceId: parts[5]
1026
1086
  });
1027
1087
  }
1028
1088
  });
1029
1089
 
1030
- result.displays = parseLinesWindowsDisplaysPowershell(ssections, msections, dsections, tsections, isections);
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);
1031
1102
 
1032
1103
  if (result.displays.length === 1) {
1033
1104
  if (_resolutionX) {
@@ -1077,7 +1148,7 @@ function graphics(callback) {
1077
1148
  function parseLinesWindowsControllers(sections, vections) {
1078
1149
  const memorySizes = {};
1079
1150
  for (const i in vections) {
1080
- if (Object.hasOwn(vections, i)) {
1151
+ if ({}.hasOwnProperty.call(vections, i)) {
1081
1152
  if (vections[i].trim() !== '') {
1082
1153
  const lines = vections[i].trim().split('\n');
1083
1154
  const matchingDeviceId = util.getValue(lines, 'MatchingDeviceId').match(/PCI\\(VEN_[0-9A-F]{4})&(DEV_[0-9A-F]{4})(?:&(SUBSYS_[0-9A-F]{8}))?(?:&(REV_[0-9A-F]{2}))?/i);
@@ -1100,7 +1171,7 @@ function graphics(callback) {
1100
1171
 
1101
1172
  const controllers = [];
1102
1173
  for (const i in sections) {
1103
- if (Object.hasOwn(sections, i)) {
1174
+ if ({}.hasOwnProperty.call(sections, i)) {
1104
1175
  if (sections[i].trim() !== '') {
1105
1176
  const lines = sections[i].trim().split('\n');
1106
1177
  const pnpDeviceId = util.getValue(lines, 'PNPDeviceID', ':').match(/PCI\\(VEN_[0-9A-F]{4})&(DEV_[0-9A-F]{4})(?:&(SUBSYS_[0-9A-F]{8}))?(?:&(REV_[0-9A-F]{2}))?/i);
@@ -1118,7 +1189,7 @@ function graphics(callback) {
1118
1189
  // PCI\VEN_v(4)&DEV_d(4)&SUBSYS_s(4)n(4)&REV_r(2)
1119
1190
  if (memorySize == null && pnpDeviceId[3] && pnpDeviceId[4]) {
1120
1191
  const deviceId = pnpDeviceId[1].toUpperCase() + '&' + pnpDeviceId[2].toUpperCase() + '&' + pnpDeviceId[3].toUpperCase() + '&' + pnpDeviceId[4].toUpperCase();
1121
- if (Object.hasOwn(memorySizes, deviceId)) {
1192
+ if ({}.hasOwnProperty.call(memorySizes, deviceId)) {
1122
1193
  memorySize = memorySizes[deviceId];
1123
1194
  }
1124
1195
  }
@@ -1126,7 +1197,7 @@ function graphics(callback) {
1126
1197
  // PCI\VEN_v(4)&DEV_d(4)&SUBSYS_s(4)n(4)
1127
1198
  if (memorySize == null && pnpDeviceId[3]) {
1128
1199
  const deviceId = pnpDeviceId[1].toUpperCase() + '&' + pnpDeviceId[2].toUpperCase() + '&' + pnpDeviceId[3].toUpperCase();
1129
- if (Object.hasOwn(memorySizes, deviceId)) {
1200
+ if ({}.hasOwnProperty.call(memorySizes, deviceId)) {
1130
1201
  memorySize = memorySizes[deviceId];
1131
1202
  }
1132
1203
  }
@@ -1134,7 +1205,7 @@ function graphics(callback) {
1134
1205
  // PCI\VEN_v(4)&DEV_d(4)&REV_r(2)
1135
1206
  if (memorySize == null && pnpDeviceId[4]) {
1136
1207
  const deviceId = pnpDeviceId[1].toUpperCase() + '&' + pnpDeviceId[2].toUpperCase() + '&' + pnpDeviceId[4].toUpperCase();
1137
- if (Object.hasOwn(memorySizes, deviceId)) {
1208
+ if ({}.hasOwnProperty.call(memorySizes, deviceId)) {
1138
1209
  memorySize = memorySizes[deviceId];
1139
1210
  }
1140
1211
  }
@@ -1142,7 +1213,7 @@ function graphics(callback) {
1142
1213
  // PCI\VEN_v(4)&DEV_d(4)
1143
1214
  if (memorySize == null) {
1144
1215
  const deviceId = pnpDeviceId[1].toUpperCase() + '&' + pnpDeviceId[2].toUpperCase();
1145
- if (Object.hasOwn(memorySizes, deviceId)) {
1216
+ if ({}.hasOwnProperty.call(memorySizes, deviceId)) {
1146
1217
  memorySize = memorySizes[deviceId];
1147
1218
  }
1148
1219
  }
@@ -1166,7 +1237,7 @@ function graphics(callback) {
1166
1237
  return controllers;
1167
1238
  }
1168
1239
 
1169
- function parseLinesWindowsDisplaysPowershell(ssections, msections, dsections, tsections, isections) {
1240
+ function parseLinesWindowsDisplaysPowershell(ssections, monitors, dsections, connections, isections, currentModes) {
1170
1241
  const displays = [];
1171
1242
  let vendor = '';
1172
1243
  let model = '';
@@ -1181,40 +1252,34 @@ function graphics(callback) {
1181
1252
  resolutionX = util.toInt(util.getValue(linesDisplay, 'ScreenWidth', ':'));
1182
1253
  resolutionY = util.toInt(util.getValue(linesDisplay, 'ScreenHeight', ':'));
1183
1254
  }
1184
- for (let i = 0; i < ssections.length; i++) {
1185
- if (ssections[i].trim() !== '') {
1186
- ssections[i] = 'BitsPerPixel ' + ssections[i];
1187
- msections[i] = 'Active ' + msections[i];
1188
- // tsections can be empty OR undefined on earlier versions of powershell (<=2.0)
1189
- // Tag connection type as UNKNOWN by default if this information is missing
1190
- if (tsections.length === 0 || tsections[i] === undefined) {
1191
- tsections[i] = 'Unknown';
1192
- }
1193
- const linesScreen = ssections[i].split('\n');
1194
- const linesMonitor = msections[i].split('\n');
1195
-
1196
- const linesConnection = tsections[i].split('\n');
1197
- 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;
1198
1267
  const bounds = util.getValue(linesScreen, 'Bounds').replace('{', '').replace('}', '').replace(/=/g, ':').split(',');
1199
1268
  const primary = util.getValue(linesScreen, 'Primary');
1200
- const sizeX = util.getValue(linesMonitor, 'MaxHorizontalImageSize');
1201
- const sizeY = util.getValue(linesMonitor, 'MaxVerticalImageSize');
1202
- const instanceName = util.getValue(linesMonitor, 'InstanceName').toLowerCase();
1203
- 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] : '';
1204
1272
  const deviceName = util.getValue(linesScreen, 'DeviceName');
1205
- let displayVendor = '';
1206
- let displayModel = '';
1207
- isections.forEach((element) => {
1208
- if (element.instanceId.toLowerCase().startsWith(instanceName) && vendor.startsWith('(') && model.startsWith('PnP')) {
1209
- displayVendor = element.vendor;
1210
- displayModel = element.model;
1211
- }
1212
- });
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;
1213
1275
  displays.push({
1214
- vendor: instanceName.startsWith(deviceID) && displayVendor === '' ? vendor : displayVendor,
1215
- model: instanceName.startsWith(deviceID) && displayModel === '' ? model : displayModel,
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,
1216
1281
  deviceName,
1217
- main: primary.toLowerCase() === 'true',
1282
+ main: hasOwnScreen ? primary.toLowerCase() === 'true' : false,
1218
1283
  builtin: videoOutputTechnology === '2147483648',
1219
1284
  connection: videoOutputTechnology && videoTypes[videoOutputTechnology] ? videoTypes[videoOutputTechnology] : '',
1220
1285
  resolutionX: util.toInt(util.getValue(bounds, 'Width', ':')),
@@ -1225,7 +1290,8 @@ function graphics(callback) {
1225
1290
  currentResX: util.toInt(util.getValue(bounds, 'Width', ':')),
1226
1291
  currentResY: util.toInt(util.getValue(bounds, 'Height', ':')),
1227
1292
  positionX: util.toInt(util.getValue(bounds, 'X', ':')),
1228
- positionY: util.toInt(util.getValue(bounds, 'Y', ':'))
1293
+ positionY: util.toInt(util.getValue(bounds, 'Y', ':')),
1294
+ currentRefreshRate: currentModes[deviceName.toLowerCase()] || null
1229
1295
  });
1230
1296
  }
1231
1297
  }
@@ -1233,6 +1299,9 @@ function graphics(callback) {
1233
1299
  displays.push({
1234
1300
  vendor,
1235
1301
  model,
1302
+ serial: null,
1303
+ productionYear: null,
1304
+ displayId: null,
1236
1305
  main: true,
1237
1306
  sizeX: null,
1238
1307
  sizeY: null,
package/lib/index.d.ts CHANGED
@@ -762,6 +762,7 @@ export namespace Systeminformation {
762
762
  restartCount: number;
763
763
  platform: string;
764
764
  driver: string;
765
+ labels: { [key: string]: string };
765
766
  ports: number[];
766
767
  mounts: DockerContainerMountData[];
767
768
  }
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) => ({}).hasOwnProperty.call(exports, 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) && {}.hasOwnProperty.call(exports, key) && data.length > i) {
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 size = parseInt(util.getValue(lines, ' Size'));
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 * 1024 * 1024 * 1024,
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 {
package/lib/osinfo.js CHANGED
@@ -190,7 +190,7 @@ function getWindowsRelease(build) {
190
190
  // FQDN
191
191
 
192
192
  function getFQDN() {
193
- let fqdn = os.hostname;
193
+ let fqdn = os.hostname();
194
194
  if (_linux || _darwin) {
195
195
  try {
196
196
  const stdout = execSync('hostname -f 2>/dev/null', util.execOptsLinux);
@@ -292,7 +292,7 @@ function osInfo(callback) {
292
292
  const distro = util.getValue(lines, 'kern.ostype');
293
293
  const logofile = getLogoFile(distro);
294
294
  const release = util.getValue(lines, 'kern.osrelease').split('-')[0];
295
- const serial = util.getValue(lines, 'kern.uuid');
295
+ const serial = util.getValue(lines, 'kern.hostuuid');
296
296
  const bootmethod = util.getValue(lines, 'machdep.bootmethod');
297
297
  const uefiConf = stdout.toString().indexOf('<type>efi</type>') >= 0;
298
298
  const uefi = bootmethod ? bootmethod.toLowerCase().indexOf('uefi') >= 0 : uefiConf ? uefiConf : null;
@@ -547,6 +547,13 @@ function versions(apps, callback) {
547
547
  const appsObj = checkVersionParam(apps);
548
548
  let totalFunctions = appsObj.counter;
549
549
 
550
+ if (totalFunctions <= 0) {
551
+ if (callback) {
552
+ callback(appsObj.versions);
553
+ }
554
+ return resolve(appsObj.versions);
555
+ }
556
+
550
557
  let functionProcessed = (() => {
551
558
  return () => {
552
559
  if (--totalFunctions === 0) {
@@ -824,6 +831,7 @@ function versions(apps, callback) {
824
831
  if (appsObj.versions.postgresql.includes('(') && postgresql.length >= 2 && !postgresql[postgresql.length - 2].includes('(')) {
825
832
  appsObj.versions.postgresql = postgresql[postgresql.length - 2];
826
833
  }
834
+ functionProcessed();
827
835
  } else {
828
836
  exec('pg_config --version', (error, stdout) => {
829
837
  if (!error) {
@@ -833,9 +841,9 @@ function versions(apps, callback) {
833
841
  appsObj.versions.postgresql = postgresql[postgresql.length - 2];
834
842
  }
835
843
  }
844
+ functionProcessed();
836
845
  });
837
846
  }
838
- functionProcessed();
839
847
  });
840
848
  }
841
849
  }
@@ -1151,7 +1159,6 @@ function shell(callback) {
1151
1159
  process.nextTick(() => {
1152
1160
  if (_windows) {
1153
1161
  try {
1154
- const result = 'CMD';
1155
1162
  util.powerShell(`Get-CimInstance -className win32_process | where-object {$_.ProcessId -eq ${process.ppid} } | select Name`).then((stdout) => {
1156
1163
  let result = 'CMD';
1157
1164
  if (stdout) {
@@ -1166,9 +1173,9 @@ function shell(callback) {
1166
1173
  });
1167
1174
  } catch {
1168
1175
  if (callback) {
1169
- callback(result);
1176
+ callback('CMD');
1170
1177
  }
1171
- resolve(result);
1178
+ resolve('CMD');
1172
1179
  }
1173
1180
  } else {
1174
1181
  let result = '';
@@ -1258,9 +1265,13 @@ echo -n "hardware: "; cat /sys/class/dmi/id/product_uuid 2> /dev/null; echo;`;
1258
1265
  result.os = util.getValue(lines, 'os').toLowerCase();
1259
1266
  result.hardware = util.getValue(lines, 'hardware').toLowerCase();
1260
1267
  if (!result.hardware) {
1261
- const lines = fs.readFileSync('/proc/cpuinfo', { encoding: 'utf8' }).toString().split('\n');
1262
- const serial = util.getValue(lines, 'serial');
1263
- result.hardware = serial || '';
1268
+ try {
1269
+ const lines = fs.readFileSync('/proc/cpuinfo', { encoding: 'utf8' }).toString().split('\n');
1270
+ const serial = util.getValue(lines, 'serial');
1271
+ result.hardware = serial || '';
1272
+ } catch {
1273
+ result.hardware = '';
1274
+ }
1264
1275
  }
1265
1276
  if (callback) {
1266
1277
  callback(result);