Обнаружение остановки в службе окна

У меня есть служба Windows, которая получает информацию о пользователе и сохраняет результат в текстовом файле журнала. и, моя проблема в том, что когда я закрываю или выхожу из системы, я также хотел бы сохранить время, в течение которого моя система попала в этот файл журнала. но я не знаю, как это сделать.

Я проверил метод winproc для обнаружения операции выключения, но я не смог использовать его в службе окна, при поиске в Google обнаружил, что он может использоваться только с формами. как мы можем обнаружить, что пользователь нажал на выключение или вышел из системы и сделал некоторые действия. поэтому, пожалуйста, дайте мне некоторое представление или предложение об этом.

Я использовал его для выхода из системы, но запись в журнале происходит, когда я выхожу из системы

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

Ответы

Ответ 1

Для выключения переопределите метод OnShutdown:

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

Для выхода из системы:

Сначала добавьте обработчик событий в Microsoft.Win32.SystemEvents.SessionEnded в Service Constructor:

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
}

Это должно поймать любой завершенный сеанс, включая сам консоль (тот, который запускает службы).

Ответ 2

Я знаю, что я воспитываю это из мертвых, но я нашел его полезным и надеюсь добавить немного к теме. Я реализую дубликатную библиотеку WCF, размещенную в службе Windows, и наткнулся на этот поток, потому что мне нужно было обнаружить изнутри службы Windows, когда пользователь выходит из системы или выключает компьютер. Я использую .Net Framework 4.6.1 для Windows 7 и Windows 10. Как и ранее предлагаемое для отключения то, что сработало для меня, было переопределение 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;

Ответ 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();
}

Edit:
Если вы действительно хотите прослушать событие выключения Microsoft.Win32.SystemEvents.SessionEnding, это путь.

Ответ 4

Возможно, вы можете использовать this. Опрос метода, о котором идет речь, время от времени (интервал в 1 секунду), и вы сможете делать то, что хотите.

Вам нужен RegisterServiceCtrlHandlerEx вызов API.