Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Windows-Benutzer-Leerlaufzeit (https://www.delphipraxis.net/194518-windows-benutzer-leerlaufzeit.html)

Der schöne Günther 1. Dez 2017 13:24

Windows-Benutzer-Leerlaufzeit
 
Ich möchte die Zeit wissen wie lang der Benutzer vor Ort keine Eingaben mehr vorgenommen hat (Touchscreen, Maus, Tastatur). Hier hilft einem die Windows-Routine GetLastInputInfo(..)

Implementiert habe ich das bislang so:

Delphi-Quellcode:
uses System.TimeSpan, WinApi.Windows;

function TTimes.getSinceLastInput(): TTimeSpan;
var
   lastInput: TLastInputInfo;
begin
   lastInput := Default(TLastInputInfo);
   lastInput.cbSize := SizeOf(TLastInputInfo);

   Win32Check( GetLastInputInfo(lastInput) );

   Result := TTimeSpan.FromMilliseconds( GetTickCount64() - lastInput.dwTime );
end;
Das Problem hierbei:
Delphi-Quellcode:
lastInput.dwTime
ist ein DWORD, reicht also nur für 49 Tage. Danach geht es wieder bei Null weiter.


Was ist hierbei die einfachste Lösung? Statt
Delphi-Quellcode:
GetTickCount64()
einfach
Delphi-Quellcode:
GetTickCount()
nehmen da er auch das "49 Tage-Problem" hat und sich beides wieder ausgleicht?

Mir geht es nur darum festzustellen ob länger als eine Zeitspanne X keine Eingaben mehr vorgenommen wurden. Da ist es auch nicht schlimm wenn es für ein paar Millisekunden während des Überlaufens nach 49 Tagen einmal falsch liegt. Bei der jetzigen Implementierung lieget er nach 49 Tagen immer falsch :|

himitsu 1. Dez 2017 13:44

AW: Windows-Benutzer-Leerlaufzeit
 
GetTickCount <> GetTickCount64 hat rein garnichts mir GetLastInputInfo zu tun, bzw. GetLastInputInfo gibt es nur in einer Version, also egal.
GetTickCount und GetLastInputInfo nutzen zwar den seltem TimeStamp, aber dennoch kannst du das nicht mit GetTickCount64 kombinieren, da es dort keine Übereinstimmung gibt.


49 Tage lang ist bei euch keiner vorm PC?

Wenn ja, dann lass doch einfach einmal am Tag einen Timer angehn. (oder einmal die Woche/pro Monat)
Da schaust du dann, ob dein zuletzt gespeicherter TimeStamp mit GetLastInputInfo übereinstimmt.
Wenn ja dann nichts machen und die gespeicherte Zeit nutzen.
Wenn nein, dann die aktuelle Zeit minus die Offlinezeit (GetTickCount-GetLastInputInfo) rechnen und dir zusätzlich den aktuellen TimeStamp (GetLastInputInfo) speichern.
> ändert sich GetLastInputInfo nicht, war keiner da ... bzw. in sehr sehr sehr sehr sehr sehr sehr sehr sehr sehr sehr sehr sehr sehr seltenen Fällen war jemand ganz genau, auf die Millisekunde, nach 49.71026962962962962962962962963 Tagen erneut aktiv
> und dein gespeicherter TimeStamp (nicht als TickCount, sondern als was Anderes ala TDateTime) ist noch gültig, egal wie alt
> hat sich der TimeStamp (GetLastInputInfo) geändert, dann ist er nicht älter als wie dein Timer-Interval

Michael II 1. Dez 2017 15:04

AW: Windows-Benutzer-Leerlaufzeit
 
Hallo Günther

wenn ich dich richtig verstehe, dann möchtest du Delta: = jetzt - letzteAktion auch dann berechnen können, wenn der "GetTickCount Zähler" nach dem Zeitpunkt letzteAktion wieder bei 0 startete.

Wenn letzteAktion und jetzt weniger als High(Cardinal) Millisekunden (ca. 49 Tage) auseinanderliegen, dann könntest du es so tun:

Delphi-Quellcode:
function GetDeltaGTC( start : Cardinal ) : Cardinal;
var res, gtc : Cardinal;
begin
    gtc := GetTickCount;
    if ( gtc >= start ) then Result := gtc - start
    else
    begin
        res := High(Cardinal)-start;
        res := res + gtc + 1;
        Result := res;
    end;
end;

himitsu 2. Dez 2017 21:17

AW: Windows-Benutzer-Leerlaufzeit
 
So aufwändig ist es garnicht nötig, wenn man mit Überläufen rechnet.

x := GetTickCount - LastUserInput;
// oder sicherheitshalber immer mit Cast, wenn der implizite Cast durch due Zielvariable nicht ausreicht und wenn dich die Compilermeldungen stören
x := Cardinal(GetTickCount - LastUserInput);

Der schöne Günther 3. Dez 2017 08:40

AW: Windows-Benutzer-Leerlaufzeit
 
Vielen Dank für die Antworten, so werde ich es glaube ich machen: Einfach
Delphi-Quellcode:
GetTickCount64
gegen
Delphi-Quellcode:
GetTickCount
tauschen (zumindest an dieser Stelle).

Da könnte er nach genau 49.7 Tagen einmal kurz falsch liegen aber wen kümmert das 8-)

Michael II 3. Dez 2017 15:35

AW: Windows-Benutzer-Leerlaufzeit
 
Zitat:

So aufwändig ist es gar nicht nötig, wenn man mit Überläufen rechnet.
Wir testen Programmteile halt immer auch mit eingeschalteter Überlaufprüfung. Und dann sind Dinge wie

Delphi-Quellcode:
x := GetTickCount - LastUserInput;
unangenehm, weil im Fall GetTickCount < LastUserInput eine Integerüberlauf-Exception ausgelöst (und x nicht berechnet) wird - und der Code beim Testen somit durchfällt.

Bei ausgeschalteter Überlaufprüfung wird keine Exception ausgelöst und es wird "richtig" gerechnet.


Zitat:

Da könnte er nach genau 49.7 Tagen einmal kurz falsch liegen aber wen kümmert das
In der Release Version hast du wahrscheinlich/sicher Überlaufprüfung auf AUS. Dann rechnet dein Programm auch dann richtig, wenn GetTickCount < LastUserInput - dein Programm wird also nach Ersetzen von GetTickCount64 durch GetTickCount korrekte Werte berechnen (solange der letzte Userinput nicht mehr als 49 Tage zurückliegt):

Delphi-Quellcode:
var a, b , res : cardinal;
begin
  a := high(cardinal);
  b := 0;
  res := b-a;
res=1

Der schöne Günther 3. Dez 2017 16:11

AW: Windows-Benutzer-Leerlaufzeit
 
Ja. Das Integer-Exception-Problem sehe ich nicht auftreten, denn in meinem Fall ist die Variable x kein DWORD oder irgendein Unsigned-Typ sondern ein Double (Parameter von
Delphi-Quellcode:
TTimeSpan.FromMilliseconds(..)
) ;-)

HolgerX 3. Dez 2017 16:25

AW: Windows-Benutzer-Leerlaufzeit
 
Hmm..

Mal eine Frage:
Muss es überhaupt GetTickCount sein?

Reichen nicht die Millisekunden von TDateTime?

Mit Now die Startzeit vom Idle nehmen und dann kann mit MilliSecondsBetween die Differenz zum Ende von Idle ermittelt werden.
Aufsummieren und schon haste die Gesamtzeit in ms.

Für eine (einfache) Erfassung sollte dies auch ohne Überlauf ausreichen.

Der schöne Günther 3. Dez 2017 16:32

AW: Windows-Benutzer-Leerlaufzeit
 
Woher soll ich wissen wann ich Now() aufrufen soll um den Zeitstempel zu aktualisieren und wann nicht? Das verstehe ich nicht.

GetLastInputInfo() liefert einen fertigen Zeitstempel wann jemand die aktuelle Windows-Sitzung das letzte mal bedient hat. Bis auf den Überlauf eigentlich schön einfach.

himitsu 3. Dez 2017 19:16

AW: Windows-Benutzer-Leerlaufzeit
 
Ihr wisst aber, dass man die Überlaufprüfung um die Stelle mit dem Überlauf auch deaktivieren kann?


Alle Zeitangaben in WEZ +1. Es ist jetzt 12:58 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz