2

我有兴趣收听会话 0 中运行的 Windows 服务的注销事件

  • 同时也知道是哪个用户正在注销(他们的会话 ID)
  • 注意我在这里说的是可取消的注销事件,而不是注销事件

如何找出哪个用户正在注销 - 从SessionEndingEventArgs获取会话 ID ?

protected override void OnStart(string[] args)
    {
        SystemEvents.SessionEnding += SystemEvents_SessionEnding;
    }

private void SystemEvents_SessionEnding(object sender, SessionEndingEventArgs e)
    {
        // SessionEndingEventArgs does not contain SID
        // or other user identifying info?
    }

[而且我还没有测试Windows 服务是否可以实际捕获 SessionEnding 事件]


或者可以使用SessionChangeDescription来识别即将注销的用户?

public ServiceApp()
    {
        CanHandleSessionChangeEvent = true;
    }

protected override void OnSessionChange(SessionChangeDescription changeDescription)
    {
        // Although changeDescription has SessionId property
        // I'm not sure it has the equivalent of session ending event?
        base.OnSessionChange(changeDescription);
    }

其他事件源?

  • 或者Cassia是否提供此类事件,包括用户帐户信息?
  • 或者我可以从某个地方的 WMI 中提取它吗?
  • 或者直接使用一些Win32 API?
4

1 回答 1

3

WM_QUERYENDSESSION在关闭会话中发送到桌面上的所有顶级窗口。但是,由于您的服务通常在不同的会话中运行,您通常不会收到通知。在 Vista 之前,您可以启用与桌面的交互以与会话 0 上的用户共享桌面,但如果注销发生在另一个会话中,您将不会收到发送给您的消息。在 XP 之后,由于会话 0 隔离,您将不会收到来自用户会话的消息。

要将此消息通知您的服务,您需要在每个会话中运行一个代理进程(即,注册以在用户通过开始菜单快捷方式或注册表登录时自动启动)并监听 WM_QUERYENDSESSION(在 .Net 术语中,运行消息泵(如 Windows 窗体中的 Application.Run 并订阅 SystemEvents.SessionEnding),然后收集会话信息并通过命名管道等进程间通信方法将通知发送到您的服务(如果您使用 WCF,请使用 NetNamedPipeBinding)。如果要获取当前会话,请使用 WTSQuerySessionInformation(或在 .Net 术语中,Process.GetCurrentProcess().SessionId)

OnSessionChange 方法在用户注销后调用。SENS 的注销事件也是如此,所以这两个对你来说太晚了。

于 2013-06-28T15:26:45.633 回答