Wykrywanie bezczynności we wszystkich sesjach

0

Witajcie!
Męczę się od jakiegoś czasu nad wykrywaniem bezczynności systemu (brak korzystania z myszki i klawiatury przez X min). Znalazłem rozwiązanie jak sprawdzić stan bezczynności ale tylko w bieżącej sesji (za pomocą GetLastInputInfo()), ale jak rozwiązać ten problem we wszystkich sesjach?

Rozwijając problem:
Uruchamiam system, razem ze startem uruchamiam usługę wykorzystującą GetLastInputInfo() (sesja 0). Potem użytkownik loguje się (sesja 1), pracuje normalnie, więc system nie jest bezczynny. Natomiast w sesji 0 usługa "widzi", że system jest bezczynny.

Ktoś pomoże?
Pozdrawiam
Sc0li0sis

0

Wielkie dzięki za szybką (i to bardzo) odpowiedź.

Niestety nawał pracy i przeciwności losu sprawiły, ze mogłem przetestować udzieloną podpowiedź dopiero w weekend. Funkcja LsaEnumerateLogonSessions i następnie LsaGetLogonSessionData podaje mi na starcie ok 13-14 różnych sesji (niekiedy Id są takie same). Tak uzyskane dane nie pomagają mi wykryć bezczynności w sesji. :( Albo po prostu ja tego nie potrafię.

Nim przejdę dalej wytłumaczę jak chcę wykrywać bezczynność systemu we wszystkich sesjach.

  1. W każdej sesji uruchamiam mały programik (nazwijmy go "_idle", który za pomocą GetLastInputInfo sprawdza jak długo w danej sesji użytkownik nie korzysta z myszki i klawiatury. Uruchamiam go za pomocą harmonogramu zadań: dla sesji "zerowej" jako trigger daję "przy uruchamianiu", natomiast dla sesji interaktywnych (z użytkownikiem) "po zalogowaniu:"
  2. Gdy program _idle ustali, że w danej sesji nie było interakcji z użytkownikiem dłużej niż zadany czas sprawdza, w jakiej sesji został uruchomiony
    a) jeżeli jest to sesja 0 - sprawdza, czy jest inna sesja "aktywna" jeżeli tak to nic nie robi, jeżeli nie to znaczy, że nikt się jeszcze nie zalogował (albo był zalogowany i się wylogował) i program wyłącza
    komputer
    b) jeżeli sesja jest różna od sesji 0 (tzn. program został uruchomiony po zalogowaniu się użytkownika) to sprawdza czy jest to sesja aktywna, jeżeli tak to wyłącza komputer, jeżeli nie to nic nie robi

Taki sobie algorytm wymyśliłem. Nie wiem czy jest on poprawny - mam nadzieję, że tak. Jeżeli znacie/wymyślicie jakiś lepszy, bardziej optymalny - jestem otwarty na propozycje :-)

Z pkt 2b sobie poradziłem, natomiast z pkt 2a mam problem:

Korzystając z podpowiedzi @_13th_Dragon znalazłęm jeszcze inny zestaw funkcji dający informacje o sesjach: WTSEnumerateSessions oraz WTSQuerySessionInformation. W sesji 0 za pomocą obu tych funkcji sprawdzam czy istnieje jakaś aktywna sesja tzn. ze statusem WTSActive.
Przy testach wyniki z poniższego kodu zapisywałem do pliku txt, aby później po zalogowaniu się można było przeglądnąć wyniki.

var 
  Sessions: PWTS_SESSION_INFO;
  NoSessions, NumBytes, ActSession: DWORD;
  UserName: string;
  pc: PChar;
  i: integer;

  begin
  WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, Sessions, NoSessions) 
  try
  if NoSessions > 0 then
    begin
      for i := 0 to NoSessions-1 do
        begin
           if Sessions^.State = WTSActive then 
               if WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, Session^.SessionId, WTSUserName, pc, NumBytes) then 
                  begin 
                    UserName:= pc;
                    ActSession:= Session^.SessionId;  
                  end; 
           Inc(Sessions);
        end; 
    end; 
  finally
      WTSFreeMemory(Sessions);
   end;                                                
end;

I co się okazuje: Po uruchomieniu komputera, ale jeszcze przed zalogowaniem się dowolnego użytkownika, system znajduje mi jedną aktywną sesję z użytkownikiem, który ostatnio był zalogowany (czyli tym, który po uruchomieniu woła o hasło). Na logikę w tym momencie nie powinno być żadnej aktywnej sesji (tak się mi wydaje).

Co robię źle? A może wszystko?
Jestem otwarty na wszelkie sugestie.

0

@Sc0li0sis Po uruchomieniu komputera, ale jeszcze przed zalogowaniem się dowolnego użytkownika, system znajduje mi jedną aktywną sesję z użytkownikiem, który ostatnio był zalogowany (czyli tym, który po uruchomieniu woła o hasło). Na logikę w tym momencie nie powinno być żadnej aktywnej sesji (tak się mi wydaje).

To może być jakaś głęboko ukryta logika Windowsa :) Albo nowa funkcja.
Bo też zauważyłem że po uruchomieniu ponownym i zalogowaniu na drugiego użytkownika jest komunikat przy zamykaniu systemu że ten poprzedni użytkownik jest zalogowany, ale nie analizowałem czy jakieś procesy są tego starego użytkownika

0

OP pyta o aktywność użytkownika (nie procesów) więc wystarczy analizować wyłącznie aktywną sesje.

0

Ale właśnie przed zalogowaniem jakiegokolwiek użytkownika mamy już jedną sesję aktywną, nie mówię tu o procesach.
Dlaczego?
Poniżej dane wyjściowe z LsaEnumerateLogonSessions i LsaGetLogonSessionData przed zalogowaniem użytkownika

 Ilość sesji: 3
 Aktualna sesja: 0
 JEST aktywna sesja o nr 1
 ----------------
 Numer sesji: 0
 State: WTSDisconnected
 UserName: 
 WTSWinStationName: Services
 ----------------
 Numer sesji: 1
 State: WTSActive
 UserName: greg
 WTSWinStationName: Console
 ----------------
 Numer sesji: 65536
 State: WTSListen
 UserName: 
 WTSWinStationName: 7A78855482A04FA781DC

Sesja 0 jest OK,
Sesja 65536 (nasłuchująca) jest OK
Ale skąd wzięła się sesja 1 i to do tego WTSActive ???

Pozdrawiam
Sc0li0sis

0

a to jest windows10 a jak się zalogujesz jako "greg" i wylogujesz to po restarcie jest tak samo ?

0

Adam, jak się wyloguję i dopiero wtedy zrestartuję komputer to jest OK:

Numer sesji: 1
State: WTSConnected
UserName:
WTSWinStationName: Console

Jak się wyloguję, a przed ponownym zalogowaniem jest podobnie.
Wygląda na to, ze przy restarcie (ale bez wcześniejszego wylogowania) Windows pamięta sesję ostatnio zalogowanego użytkownika.

Ale jak to obejść. To znaczy jak z całą pewnością stwierdzić, że mamy aktualnie zalogowanego użytkownika, a nie tylko "pamiątkę" z poprzedniego uruchomienia?
Ktoś ma jakiś pomysł.

I jeszcze jednio pytanie, czy mój pomysł/algorytm (podany wyżej) na wykrywanie bezczynności we wszystkich sesjach jest poprawny? Czy ktoś ma jakiś inny pomysł?

Pozdrawiam, licząc na pomoc "tęgich głów"
Sc0li0sis

0

Może to Cię na coś naprowadzi https://learn.microsoft.com/en-us/archive/blogs/wsl/pico-process-overview
z tego co kojarzę 0 to proces idle od 1 do 4 procesy kernel

0

Niestety, artykuł bardziej dotyczy procesów niż sesji użytkownika :-(
Sc0li0sis

0

Nikt nie ma żadnego pomysłu?
S.

0

Nie ma takich pomysłów, których byłbyś w stanie zrozumieć.
Nie pasujących do powyższej definicji dostałeś 3.

0

Dragon, spróbuj, może coś zrozumię :-)

1 użytkowników online, w tym zalogowanych: 0, gości: 1