Служба должна определить, заблокирована ли рабочая станция и включена ли заставка - PullRequest
8 голосов
/ 29 октября 2008

Я работаю над сервисом, который должен обнаруживать пользовательские состояния для всех пользователей, вошедших в систему на одном компьютере. В частности, я хочу проверить, активна ли заставка и заблокирован ли их сеанс.

Этот код будет работать под управлением системного уровня и не имеет видимого пользовательского интерфейса, что может исключить несколько вариантов (перехват сообщений WM и т. Д.).

Помимо обычных рабочих станций, я бы хотел, чтобы это работало на серверах терминалов, на которых подключено несколько пользователей. Из-за этих требований мне интересно, нужно ли задействовать несколько Win32 API.

Есть идеи, с чего начать?

Ответы [ 3 ]

19 голосов
/ 09 апреля 2009

В качестве услуги вы можете использовать событие OnSessionChange, чтобы перехватить все ваши важные моменты.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceProcess;
using System.Diagnostics;

namespace MyCode
{
    class MyService : ServiceBase
    {
        public MyService()
        {
            this.CanHandleSessionChangeEvent = true;
        }

        protected override void OnSessionChange(SessionChangeDescription changeDescription)
        {
            switch (changeDescription.Reason)
            {
                case SessionChangeReason.SessionLogon:
                    Debug.WriteLine(changeDescription.SessionId + " logon");
                    break;
                case SessionChangeReason.SessionLogoff:
                    Debug.WriteLine(changeDescription.SessionId + " logoff");
                    break;
                case SessionChangeReason.SessionLock:
                    Debug.WriteLine(changeDescription.SessionId + " lock");
                    break;
                case SessionChangeReason.SessionUnlock:
                    Debug.WriteLine(changeDescription.SessionId + " unlock");
                    break;
            }

            base.OnSessionChange(changeDescription);
        }
    }
}

Я уверен, что можно определить пользователя на основе changeDescription.SessionId. Но сейчас я не знаю, как ...

РЕДАКТИРОВАТЬ: Это должно быть возможность

    public static WindowsIdentity GetUserName(int sessionId)
    {
        foreach (Process p in Process.GetProcesses())
        {
            if(p.SessionId == sessionId) {                    
                return new WindowsIdentity(p.Handle);                          
            }                
        }
        return null;
    }

Ссылки MSDN

4 голосов
/ 29 октября 2008

Самый простой способ - это запустить небольшое приложение в сеансе каждого пользователя. Каждый экземпляр этого приложения может взаимодействовать с основным экземпляром службы.

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

2 голосов
/ 09 апреля 2009

Более простым решением было бы использование Cassia , которая охватывает различные API-интерфейсы TS, для проверки того, как долго пользователи простаивают:

using Cassia;

foreach (ITerminalServicesSession session in new TerminalServicesManager().GetSessions())
{
    if ((session.CurrentTime - session.LastInputTime > TimeSpan.FromMinutes(10)) &&
        (!string.IsNullOrEmpty(session.UserName)))
    {
        Console.WriteLine("Session {0} (User {1}) is idle", session.SessionId, session.UserName);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...