代码之家  ›  专栏  ›  技术社区  ›  Brian Cline

服务需要检测工作站是否被锁定,屏幕保护程序是否处于活动状态。

  •  8
  • Brian Cline  · 技术社区  · 17 年前

    我正在开发一项服务,它需要检测所有登录到一台机器上的用户的状态。具体来说,我想检查屏幕保护程序是否处于活动状态,以及它们的会话是否被锁定。

    此代码将在系统级服务下运行,并且没有可见的UI,因此可能会排除几个选项(捕获WM消息等)。

    除了普通的工作站之外,我希望它可以在有多个用户登录的终端服务器上工作。由于这些要求,我想知道是否需要涉及几个win32 API。

    关于从哪里开始有什么想法吗?

    3 回复  |  直到 17 年前
        1
  •  4
  •   Tim Robinson    17 年前

    最简单的方法是在每个用户的会话中运行一个小应用程序。此应用程序的每个实例都可以与服务的主实例通信。

    Windows很难让登录会话保持独立——服务和交互桌面之间,以及各个终端服务会话之间——所以访问关于用户会话的此类信息非常困难,除非您的应用程序首先运行在该会话中。

        2
  •  19
  •   Michael Piendl    17 年前

    作为一个系列,您可以使用事件OnSessionChange来捕捉所有相关的时刻。

    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);
            }
        }
    }
    

    我确信可以根据changedescription.sessionid识别用户。但现在我不知道怎么…

    编辑:这应该是一种可能性

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

    MSDN链路

        3
  •  2
  •   Dan Ports    17 年前

    一个简单的解决方案是 Cassia 它包装了各种TS API,以检查用户空闲多长时间:

    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);
        }
    }
    
    推荐文章