Как можно подписаться на события входа и выхода пользователя в Windows Service, используя .NET 9?

Я создал Windows-сервис по <a href="https://learn.microsoft.com/en-us/dotnet/core/extensions/windows-service" rel="nofollow">туториалу</a>. <br/> Сервис запускается автоматически от имени Local System. <br/> Как я могу подписаться на события входа/выхода пользователя, чтобы фиксировать, кто и когда залогинился локально или через RDP?
  • 26 февраля 2025 г. 10:04
Ответы на вопрос 2
Чтобы подписаться на события входа и выхода пользователей в Windows-сервисе, вы можете использовать Windows Management Instrumentation (WMI) или системы журналирования событий. В .NET 9 есть поддержка работы с WMI и EventLog, поэтому вы можете использовать один из этих подходов.

Вот пример, как вы можете реализовать подписку на события входа/выхода с помощью WMI:

1. **Добавьте ссылку на WMI**: Убедитесь, что у вас есть необходимые зависимости в проекте (обычно они уже подгружаются с помощью .NET SDK).

2. **Создайте класс для обработки событий**:
   
```csharp
using System;
using System.Management;
using System.ServiceProcess;

public class MyService : ServiceBase
{
    private ManagementEventWatcher _watcher;

    protected override void OnStart(string[] args)
    {
        // Подписка на события входа и выхода
        SubscribeToUserLoginEvents();
    }

    protected override void OnStop()
    {
        // Очистка подписок
        _watcher.Stop();
        _watcher.Dispose();
    }

    private void SubscribeToUserLoginEvents()
    {
        // Запрос для входа в систему
        var query = "SELECT * FROM __InstanceCreationEvent WITHIN 1 WHERE TargetInstance ISA 'Win32_LogonSession'";
        _watcher = new ManagementEventWatcher(query);
        _watcher.EventArrived += new EventArrivedEventHandler(OnUserLoggedIn);
        _watcher.Start();
    }

    private void OnUserLoggedIn(object sender, EventArrivedEventArgs e)
    {
        // Обработка события входа
        var logonSession = (ManagementBaseObject)e.NewEvent["TargetInstance"];
        Console.WriteLine($"User logged in: {logonSession["LogonType"]}, User: {logonSession["Name"]} at {DateTime.Now}");
    }
}
```

3. **Добавьте обработку выхода пользователя**:
   
Также добавьте дополнительный слушатель для событий завершения работы сессий, используя класс `__InstanceDeletionEvent`:

```csharp
private void SubscribeToUserLogoutEvents()
{
    var query = "SELECT * FROM __InstanceDeletionEvent WITHIN 1 WHERE TargetInstance ISA 'Win32_LogonSession'";
    var logoutWatcher = new ManagementEventWatcher(query);
    logoutWatcher.EventArrived += new EventArrivedEventHandler(OnUserLoggedOut);
    logoutWatcher.Start();
}

private void OnUserLoggedOut(object sender, EventArrivedEventArgs e)
{
    // Обработка события выхода
    var logonSession = (ManagementBaseObject)e.NewEvent["TargetInstance"];
    Console.WriteLine($"User logged out: {logonSession["LogonType"]}, User: {logonSession["Name"]} at {DateTime.Now}");
}
```

4. **Запуск сервиса**:
   После того как вы добавите необходимую логику подписки на события, вы можете собрать и установить ваш сервис.

### Альтернативный метод с использованием журнала событий
Если вы хотите использовать журнал событий, это может потребовать больше кода, так как вам нужно будет прослушивать события в журнале событий Windows. 

В случае, если вам потребуется более сложная обработка или фильтрация, вы можете рассмотреть использование библиотек, таких как `NLog` или `Serilog`, чтобы логировать события в файл или базу данных.

Эти примеры используют WMI для отслеживания событий, но имейте в виду, что могут потребоваться права администратора для доступа к необходимым ресурсам.
Отслеживать события в журнале безопасности: 
4624: An account was successfully logged on
4634: An account was logged off

Если речь именно про подписку на события - Event Log Subscriptions (Forwarding) - то настраиваете на своей машине коллектор, на наблюдаемой машине настраиваете подписку на нужные события (4624, 4634). Дальше на своей машине разбираете подписочные события для получения имен пользователей, типа входа и т.д.
Похожие вопросы