Service needs to detect if workstation is locked, and screen saver is active

后端 未结 3 740
傲寒
傲寒 2020-12-13 11:32

I\'m working on a service that needs to detect user states for all user(s) logged on to a single machine. Specifically, I want to check to see whether or not the screen save

相关标签:
3条回答
  • 2020-12-13 11:54

    The most straightforward way would be to have a small app running in each user's session. Each instance of this app could communicate with the main instance of the service.

    Windows tries pretty hard to keep logon sessions separate -- both between services and the interactive desktop, and between individual Terminal Services sessions -- so it gets very tricky to access this sort of information about a user's session unless your app is running in that session to begin with.

    0 讨论(0)
  • 2020-12-13 12:00

    As a serivce you can use the event OnSessionChange to catch all your relevant moments.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.ServiceProcess;
    using System.Diagnostics;
    
    namespace MyCode
    {
        class MyService : ServiceBase
        {
            public MyService()
            {
                this.CanHandleSessionChangeEvent = true;
            }
    
            protected override void OnSessionChange(SessionChangeDescription changeDescription)
            {
                switch (changeDescription.Reason)
                {
                    case SessionChangeReason.SessionLogon:
                        Debug.WriteLine(changeDescription.SessionId + " logon");
                        break;
                    case SessionChangeReason.SessionLogoff:
                        Debug.WriteLine(changeDescription.SessionId + " logoff");
                        break;
                    case SessionChangeReason.SessionLock:
                        Debug.WriteLine(changeDescription.SessionId + " lock");
                        break;
                    case SessionChangeReason.SessionUnlock:
                        Debug.WriteLine(changeDescription.SessionId + " unlock");
                        break;
                }
    
                base.OnSessionChange(changeDescription);
            }
        }
    }
    

    I'm sure it is possible to identify the user based on changeDescription.SessionId. But at the moment i don't know how...

    EDIT: This should be a possibilty

        public static WindowsIdentity GetUserName(int sessionId)
        {
            foreach (Process p in Process.GetProcesses())
            {
                if(p.SessionId == sessionId) {                    
                    return new WindowsIdentity(p.Handle);                          
                }                
            }
            return null;
        }
    

    MSDN Links

    • system.serviceprocess.servicebase.onsessionchange
    • system.serviceprocess.sessionchangedescription
    • system.serviceprocess.sessionchangereason
    0 讨论(0)
  • 2020-12-13 12:04

    A simpler solution would be to use Cassia, which wraps the various TS APIs, to check how long users have been idle for:

    using Cassia;
    
    foreach (ITerminalServicesSession session in new TerminalServicesManager().GetSessions())
    {
        if ((session.CurrentTime - session.LastInputTime > TimeSpan.FromMinutes(10)) &&
            (!string.IsNullOrEmpty(session.UserName)))
        {
            Console.WriteLine("Session {0} (User {1}) is idle", session.SessionId, session.UserName);
        }
    }
    
    0 讨论(0)
提交回复
热议问题