2008-10-29 62 views
8

我正在研究需要检测登录到单台计算机上的所有用户的用户状态的服务。具体来说,我想检查屏幕保护程序是否处于活动状态,以及他们的会话是否被锁定。服务需要检测工作站是否锁定,并且屏幕保护程序处于活动状态

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

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

任何想法从哪里开始?

回答

4

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

Windows非常难以保持登录会话分开 - 在服务和交互式桌面之间以及在单独的终端服务会话之间 - 所以访问有关用户会话的这类信息非常棘手,除非您的应用程序是在该会话中运行以开始。

+0

谢谢,我会放弃这一点。也许一个简单的套接字将是最好的方式来做到这一点。 – 2008-10-29 20:53:38

1

屏保应该有扩展名.scr的,你可以查询正在运行的进程......

2

一个简单的办法是使用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); 
    } 
} 
19

作为一个服务,您可以使用事件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来识别用户。但此刻我不知道如何...

编辑:这应该是一个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链接

+0

GetUserName代码不适用于我(引发异常)。不过,我在这里找到了代码,它需要执行以下操作:http://msmvps.com/blogs/siva/archive/2006/10/02/Getting-Windows-Process-Owner-Name.aspx – Kramii 2011-06-08 10:03:44