检测窗口服务中的关闭

时间:2011-03-05 06:22:29

标签: c# .net windows-services

我有一个获取用户详细信息的Windows服务,并将结果保存到日志文本文件中。而且,我的问题是当我关闭或注销我的系统时,我也希望将我的系统中的时间保存到该日志文件中。但是,我不知道该怎么做。

我检查了winproc方法来检测关机操作,但我无法在窗口服务上使用它,谷歌搜索发现它只能用于表单。我们如何检测用户是否已点击关机或注销并执行某些操作。 所以,请给我一些想法或建议。

我已经将它用于注销,但是当我注销系统时会进行日志输入

  protected override void OnSessionChange(SessionChangeDescription changeDescription)
  {
     this.RequestAdditionalTime(250000); //gives a 25 second delay on Logoff
     if (changeDescription.Reason == SessionChangeReason.SessionLogoff)
     {
        // Add your save code here
        StreamWriter str = new StreamWriter("D:\\Log.txt", true);
        str.WriteLine("Service stoped due to " + changeDescription.Reason.ToString() + "on" + DateTime.Now.ToString());
        str.Close();
     }
     base.OnSessionChange(changeDescription);
 }

5 个答案:

答案 0 :(得分:15)

对于关机,请覆盖OnShutdown方法:

protected override void OnShutdown()
{
    //your code here
    base.OnShutdown();
}

注销:

首先,在Service Constructor中向Microsoft.Win32.SystemEvents.SessionEnded添加一个事件处理程序:

public MyService()
{
    InitializeComponent;
    Microsoft.Win32.SystemEvents.SessionEnded += new Microsoft.Win32.SessionEndedEventHandler(SystemEvents_SessionEnded);
}

然后添加处理程序:

void SystemEvents_SessionEnded(object sender, Microsoft.Win32.SessionEndedEventArgs e)
{
    //your code here
}

这应该捕获任何已结束的会话,包括控制台本身(运行服务的那个)。

答案 1 :(得分:9)

我知道我是从死里复活的,但我觉得它很有帮助,并希望在这个主题上添加一些内容。我正在实现Windows服务中托管的WCF双工库并遇到了这个线程,因为我需要在Windows服务中检测用户何时注销或关闭计算机。我在Windows 7和Windows 10上使用.Net Framework 4.6.1。就像之前建议的关闭一样,对我有用的是覆盖ServiceBase.OnShutdown(),如下所示:

protected override void OnShutdown()
{
    //Your code here

    //Don't forget to call ServiceBase OnShutdown()
    base.OnShutdown();
}

请记住将以下内容添加到服务的构造函数中以允许捕获关闭事件:

CanShutdown = true;

然后捕获用户注销时,锁定屏幕,切换用户等等,你可以像这样覆盖OnSessionChange方法:

protected override void OnSessionChange(SessionChangeDescription changeDescription)
{
    if (changeDescription.Reason == SessionChangeReason.SessionLogoff)
    {
        //Your code here...

        //I called a static method in my WCF inbound interface class to do stuff...
    }

    //Don't forget to call ServiceBase OnSessionChange()
    base.OnSessionChange(changeDescription);
}

当然记得将以下内容添加到服务的构造函数中以允许捕获会话更改事件:

CanHandleSessionChangeEvent = true;

答案 2 :(得分:3)

您应该覆盖服务中的OnShutdown

// When system shuts down
protected override void OnShutdown()
{
    // Add your save code here
    base.OnShutdown();
}

您可能还想覆盖OnStop

// When the user presses stops your service from the control panel
protected override void OnStop()
{
    // Add your save code here too
    base.OnStop();
}

修改
如果你真的想听关机事件Microsoft.Win32.SystemEvents.SessionEnding,那就是你要走的路。

答案 3 :(得分:1)

也许你可以使用this。不时轮询有问题的方法(1秒间隔),你就能做你想做的事。

您需要RegisterServiceCtrlHandlerEx API调用。

答案 4 :(得分:1)

免责声明

当Windows再次关闭关闭行为时,此答案可能不会有用。

计算机关闭时会出现哪些通知?

据我所知,计算机关闭时会出现三个通知:

  • SessionLogoff
  • SessionLock
  • Suspend

前两个由OnSessionChange()传递,最后一个由OnPowerEvent()传递。

当然,Suspend是很自然的选择,但是请注意,将计算机发送到睡眠时也会发送此通知。

如何获得通知?

要获取上面发布的通知,您必须按如下所示在服务构造函数中允许这些通知:

public Service1()
{
    InitializeComponent();

    CanHandlePowerEvent = true;
    CanHandleSessionChangeEvent = true;
}

然后覆盖相应的

protected override void OnSessionChange(SessionChangeDescription changeDescription)
{
    // Do something
    base.OnSessionChange(changeDescription);
}

protected override bool OnPowerEvent(PowerBroadcastStatus powerStatus)
{
    // Do something
    return base.OnPowerEvent(powerStatus);
}

那ServiceBase.OnShutdown()呢?

好吧,通过单击“电源”选项中的“关闭”来关闭计算机时,不会调用此方法。

确实this official post中所写,

关闭计算机时,计算机实际上进入了休眠状态,而不是完全关闭。

此外,根据the documentation

使用OnShutdown指定系统关闭时发生的处理。

仅当操作系统关闭时才会发生此事件,而在计算机关闭时则不会发生。

当CanShutdown属性为true时,OnShutdown应该会被覆盖。

因此,如果手动关闭计算机并没有真正关闭计算机,而是使计算机进入了休眠状态,那么什么可以关闭计算机呢?

post quoted above再次给出答案:

仅当您重新启动计算机或其他事件导致计算机处理完全关闭时,才会发生完全关闭。

实际上,我可以通过设置来在服务上调用OnShutdown()方法

CanShutdown = true;

并覆盖到OnShutdown

protected override void OnShutdown()
{
    // Do something
    base.OnShutdown();
}

然后重新启动计算机。


这个帖子足够了。我只希望Windows的关闭行为不会很快改变...