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.
- 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:"
- 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.