简体   繁体   English

如何知道Windows服务是否有活动的交互式会话?

[英]How to know if there is an interactive session active from windows service?

I'm coding a windows service and in one point I need to know if there is an active interactive session. 我正在编写Windows服务,有一点我需要知道是否存在活动的交互式会话。

I tried using OnSessionChange() and keep in a variable the last SessionChangeReason. 我尝试使用OnSessionChange()并在变量中保留最后一个SessionChangeReason。 When I reach to the mentioned point I compare if it's equal to SessionChangeReason.SessionLogOn. 当我达到上述要点时,我会比较它是否等于SessionChangeReason.SessionLogOn。 This works with the inconvenient that the service has a delayed start so if the user logs on before the service starts running this information is lost. 这有助于服务延迟启动的不便,因此如果用户在服务开始运行之前登录,则此信息将丢失。

I have also seen the System.Environment.Interactive property but as I understand this refers to the process of the current service which is not interactive, so it wouldn't give me the information I need (I might misunderstood this, though). 我也看过System.Environment.Interactive属性,但据我所知,这是指当前服务的进程,它不是交互式的,所以它不会给我我需要的信息(我可能会误解这一点)。

Is there a way to get this info 'on demand' without having to keep register of the SessionChangeReason? 有没有办法在不需要注册SessionChangeReason的情况下“按需”获取此信息?

Edit: Maybe I wasn't clear about this point. 编辑:也许我不清楚这一点。 Aside from knowing that there is an interactive session I also need to know that it isn't locked. 除了知道存在交互式会话之外,我还需要知道它没有被锁定。

P/Invoke WTSEnumerateSessions to see if there are additional sessions and what their connected states are. P /调用WTSEnumerateSessions以查看是否有其他会话以及它们的连接状态。 You obviously have to ignore session 0 on Vista+. 您显然必须忽略Vista +上的会话0。

You should only do this when your service is started, the session change notification should be used to detect further changes. 您应该只在启动服务时执行此操作,应使用会话更改通知来检测进一步的更改。

Finally I've resigned to knowing specifically that there is a session and isn't locked so we'll work with whether there is an active session or not. 最后,我已经辞职,明确知道有一个会话而且没有锁定,因此我们将处理是否存在活动会话。

If only knowing there is an active session works for you and you don't want to use pInvoke you can either: 如果只知道有一个活动会话适合您并且您不想使用pInvoke,您可以:

a) Search for the explorer process a)搜索资源管理器进程

Process[] ps = Process.GetProcessesByName("explorer");
bool explorerActive = (ps.Length > 0);

b) Use the following WMI query to get the UserName of the active session: b)使用以下WMI查询获取活动会话的UserName:

using System.Management;

ConnectionOptions oConn = new ConnectionOptions();
ManagementScope oMs = new ManagementScope("\\\\localhost", oConn);

ObjectQuery oQuery = new ObjectQuery("select * from Win32_ComputerSystem");
ManagementObjectSearcher oSearcher = new ManagementObjectSearcher(oMs, oQuery);
ManagementObjectCollection oReturnCollection = oSearcher.Get();


foreach (ManagementObject oReturn in oReturnCollection)
{
    if (oReturn["UserName"] == null)
    {
        // No active session
        Console.Write("UserName: null");
    }
    else
    {
        // Active session
        Console.Write("UserName: " + oReturn["UserName"].ToString());
    }                            
}

If you want to use pInvoke see Anders' answer. 如果你想使用pInvoke,请参阅Anders的回答。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM