detect rdp sessions too for idletime #7554

Signed-off-by: si458 <simonsmith5521@gmail.com>

si458 committed Feb 18, 2026 at 11:07 UTC 71fede5961341d7add69293051f75ec0acb26137
2 files changed +50 -4
agents/meshcore.js
+4 -3
@@ -4256,7 +4256,7 @@ function processConsoleCommand(cmd, args, rights, sessionid) {
4256 break;
4257 case 'idletime':
4258 try { require('win-deskutils'); } catch (ex) { response = 'Unknown command "idletime", type "help" for list of available commands.'; break; }
4259 - response = 'idling for ' + require('win-deskutils').idle.getSeconds(null) + ' seconds';
4259 + require('win-deskutils').idle.getSecondsAllSessions().then(function (seconds) { sendConsoleText((seconds === -1 ? 'No active users' : 'Idle time for all sessions: ' + seconds + ' seconds'), sessionid); });
4260 break;
4261 case 'taskbar':
4262 try { require('win-utils'); } catch (ex) { response = 'Unknown command "taskbar", type "help" for list of available commands.'; break; }
@@ -6339,9 +6339,10 @@ function sendPeriodicServerUpdate(flags, force) {
6339
6340 // Calculate Windows Idle Time
6341 try {
6342 - var idletime = require('win-deskutils').idle.getSeconds(null);
6343 - meshCoreObj.idletime = idletime;
6342 + require('win-deskutils').idle.getSecondsAllSessions().then(function (seconds) {
6343 + meshCoreObj.idletime = seconds;
6344 meshCoreObjChanged();
6345 + });
6346 } catch (ex) { sendConsoleText('Error getting idle time: ' + ex.toString());}
6347 }
6348
agents/modules_meshcore/win-deskutils.js
+46 -1
@@ -248,7 +248,52 @@ function idle_getSeconds(tsid)
248 return Math.floor(idleMs / 1000);
249 }
250
251 +//
252 +// This function returns the minimum idle time across all active/connected user sessions.
253 +// This is useful for detecting if ANY user (console or RDP) is actively using the machine.
254 +// Returns a promise that resolves to the minimum idle seconds, or -1 if no users are logged in.
255 +//
256 +function idle_getSecondsAllSessions()
257 +{
258 + var promise = require('promise');
259 + return new promise(function (resolve, reject)
260 + {
261 + require('user-sessions').enumerateUsers().then(function (sessions)
262 + {
263 + var minIdleSeconds = Infinity;
264 + for (var sessionId in sessions)
265 + {
266 + var session = sessions[sessionId];
267 +
268 + // Only check Active sessions with a logged-in user (Username is present)
269 + // Skip "Connected" sessions (console when disconnected) and "Listening" sessions
270 + if (session.State === 'Active' && session.Username && session.Username !== '')
271 + {
272 + try
273 + {
274 + var idleSeconds = parseFloat(sessionDispatch(session.SessionId, 'idle', 'getSeconds', []));
275 + if (idleSeconds < minIdleSeconds)
276 + {
277 + minIdleSeconds = idleSeconds;
278 + }
279 + }
280 + catch (e)
281 + {
282 + // Session might not support GetLastInputInfo, skip it
283 + }
284 + }
285 + }
286 +
287 + // If no active user sessions found, return -1 to indicate "no users logged in"
288 + resolve(minIdleSeconds === Infinity ? -1 : Math.floor(minIdleSeconds));
289 + }).catch(function (err)
290 + {
291 + reject(err);
292 + });
293 + });
294 +}
295 +
296 module.exports = { background: { get: background_get, set: background_set } };
297 module.exports.mouse = { getTrails: mousetrails_get, setTrails: mousetrails_set };
253 -module.exports.idle = { getSeconds: idle_getSeconds };
298 +module.exports.idle = { getSeconds: idle_getSeconds, getSecondsAllSessions: idle_getSecondsAllSessions };
299 module.exports.dispatch = dispatch;
\ No newline at end of file