_Timer_GetIdleTime userunabhängig

  • Hallo zusammen,
    ich habe ein kleines Skript geschrieben, welches alle X Minuten die Leerlaufzeit prüft (Funktion _Timer_GetIdleTime). Wenn eine bestimmte Zeit erreicht ist, prüft es mittels CMD Befehl netstat, ob ein bestimmtes Gerät gerade eine Verbindung zum Rechner hergestellt hat. Wenn ja, mache nix sondern gehe wieder zur Prüfschleife und wenn keine Verbindung vorhanden ist, schalte den Rechner in den Energiesparmodus.

    Hintergrund: Auf dem Rechner läuft ein Mediaserver und wenn gerade ein Fernseher oder ein Smartphone eine Verbindung offen hat, soll er natürlich nicht ausgehen. Klappt soweit ganz gut. Aber....
    Das Skript liegt im Autostart des standardmäßig angemeldeten Users A. Wenn dieser nun angemeldet ist und sich zudem ein weiterer User B anmeldet, wird der User B mitten in seiner Arbeit vom Energiesparmodus überrascht, da die Funktion _Timer_GetIdleTime leider nur die Leerlaufzeit des Users ermittelt, der das Skript ausführt. Es müsste aber die Leerlaufzeit (also keine Maus- und Tastatureingaben) des gesamten Systems prüfen - unabhängig vom User.

    Hat jemand eine Idee, wie man das machen könnte bzw. gibt es eine ähnliche Funktion, die das kann?

    Ich habe schon versucht, das Skript in den Taskplaner zu packen um es userunabhängig beim Systemstart laufen zu lassen, aber da braucht es ja auch die Eingabe von Anmeldeinformationen eines (zur Ausführung berechtigten) Users...

    Besten Dank und süße Grüße,

    Schokolade

  • Nicht ganz nutzerunabhängig aber dürfte dein Problem lösen:

    Statt das Script in den Autostart eines Nutzers zu schieben könntest du es in den HKLM Schlüssel dafür schieben. (HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run)

    Das Hindernis bleibt nur noch eine wie auch immer geartete Kommunikation zwischen den Scripts. Beispielsweise über Dateien oder Registry.

    Anregungen evtl auch hier: Feststellen ob ein Anwender angemeldet ist

    Ausführlicher gerne wenn ich am Rechner bin.

    Es gibt Tage, da trete ich nicht ins Fettnäpfchen. Ich falle in die Friteuse.

  • Statt das Script in den Autostart eines Nutzers zu schieben könntest du es in den HKLM Schlüssel dafür schieben. (HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run)

    macht auf den 1. Anschein Sinn, aber dadurch bestimmt das zuletzt getartete Skript wann in Energiesparmodus geschaltet wird.

    Das Hindernis bleibt nur noch eine wie auch immer geartete Kommunikation zwischen den Scripts. Beispielsweise über Dateien oder Registry.

    das ist eineLösung, hier tut's eine einfache Ini in einem von allen les-/beschreibaren Verzeichnis
    z.B.: @AppDataCommonDir, ein Registryeintrag ist natürlich auch ein Weg.
    Vielleicht kann man aber auch ganz auf die Kommunikation verzichten in dem das (von jedem gestartete Skript) regelmäßig prüft ob sich der Rechner im Energiesparmodus befindet und vom zugeordneten User aktiv benutzt wird. Wenn ja Energiesparmodus (falls an) aus => volle Leistung ein.
    Die 1. Lösung empfinde ich als besser und nur unwesentlich scherer umzusetzen.

  • @autoBert eigentlich das zuerst gestartete. Denn das würde ohne Kommunikation eher davon überzeugt sein es müsse in den Energiesparmodus schalten da das zuletzt gestartete ja in dem Benutzerkontext des Nutzers läuft der gerade aktiv ist.

    Des Weiteren habe ich es nicht als Energieoptionen verstanden sondern als den Betriebsystemmodus - früher Standby genannt. Faktisch muss das Script auf allen Profilen laufen und die kleinste Idle-Time ermitteln.

    Es gibt Tage, da trete ich nicht ins Fettnäpfchen. Ich falle in die Friteuse.

  • Hallo Bioshade, hallo autoBert,

    erst einmal vielen Dank für eure ausführlichen Antworten und Vorschläge! :thumbup:

    Statt das Script in den Autostart eines Nutzers zu schieben könntest du es in den HKLM Schlüssel dafür schieben. (HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run)

    Das ist doch das gleiche wie wenn ich das Skript in den Autostartordner aller Benutzer lege, oder? Das habe ich schon probiert - dann läuft das Skript mehrfach und sobald eine dieser Instanzen dann die Leerlaufzeit erreicht (also die Instanz des Benutzers, der gerade nicht am Rechner arbeitet), schaltet diese in den Energiesparmodus.

    Ich verstehe nich so recht, wie ihr das meint mit der Kommunikation der Skripte. Problem ist, dass User A sich anmeldet, etwas arbeitet und dann den Rechner sperrt (sich nicht abmeldet). Dann meldet sich User B an und arbeitet. Das Skript unter User A läuft weiter und misst dessen Leerlaufzeit.

    Wie soll man das denn prüfen, ob User A den Bildschirm gesperrt hat und das Skript dann entspr. pausieren? Immer nur Skript aktivieren, wenn Bildschirm gesperrt ist geht nicht, denn es kommt auch vor, dass der User den Bildschirm nicht sperrt und weggeht.

    Ich dachte die einfachste Lösung ist es, sämtliche Maus- und Tastaturaktivitäten des Rechners (unabhängig ob ein User angemeldet ist oder nicht) zu monitoren.


    Am Rande: Mit Energiesparmodus meine ich die Möglichkeit, wie sie auch im Startmenü als "Energie sparen" verfügbar ist, also den Rechner auszuschalten und mit einer Grundspannung (knapp 6 Watt) zu versorgen, um beim Wackeln an der Maus oder beim Druck einer beliebigen Taste sofort wieder beim Anmeldebildschirm zu sein. Ich habe lange nach einer Lösung gesucht und es letztlich so gelöst:

    AutoIt
    Dim $sBefehlPSShutdown = "psshutdown.exe -d -t 5 >>" & $sDateiLogName
    Run(@ComSpec & " /c " & $sBefehlPSShutdown, @ScriptDir, @SW_HIDE)
  • Gerne kann ich dir heute Abend (etwa 2000) ein Beispielscript schreiben. Bin jetzt erst Mal an der Arbeit. Und da bin ich heute voll ausgelastet.

    Edit - Schokolade - Hier ein kleines Beispiel... eben schnell hingeschmiert, daher bisschen unstrukturiert und oftmals noch verbesserungsfähig.

    Erst einmal brauchen wir eine Liste der Nutzer, bei denen das Script aktuell läuft (im Beispiel mit dem Explorer - damit bekommst du dann die eingeloggten Nutzer generell):

    Jetzt müssten beide Scripts in eine gemeinsame Datei schreiben (z.B. in @AppDataCommonDir), welche Idle-Time sie aktuell haben. Wie oft du diesen Wert aktualisieren lässt, hängt davon ab, wie genau die Werte für dich sein müssen. Dein Script müsste dann die Idlezeiten aller eingeloggten Nutzer aus der Datei lesen, und dann prüfen, welche dieser Idle-Zeiten die niedrigste ist. Das wäre dann die System-Idle-Zeit, die du für deinen Energiesparmodus beachten müsstest. Beispielini:

    [IDLE]
    UserA=213.63634
    UserB=14.123

    Über die Funktion "_LoggedInUsers" bekommst du einen Array, in dem alle eingeloggten User aufgeführt sind. Das kannst du dann schlicht in eine kleine Funktion umbasteln:

    AutoIt
    Func _GetIdleTime_Global()
    	$aUsers = _LoggedInUsers()
    	$iIdleTime = 900*60000 ;15 Stunden
    	For $i = 0 To UBound($aUsers) - 1
    		$iIdle_User = IniRead(@AppDataCommonDir & "\IDLE.ini", "IDLE", $aUsers[$i], $iIdleTime)
    		If $iIdle_User < $iIdleTime Then $iIdleTime = $iIdle_User
    	Next
    	Return $iIdleTime
    EndFunc

    Alles was jetzt nur noch fehlt ist eine Funktion in deinem Script, dass die Idle-Time in die Ini-Datei schreibt. Diese sollte möglichst (zur Sicherheit) direkt bei Scriptstart aufgerufen werden und die IDLE-Time auf 0 setzen. Dann könntest du - beispielsweise über AdlibRegister - periodisch deine Update-Funktion aufrufen, die die Zeit in die Ini-Datei schreibt. Damit wäre der mögliche Worst-Case der mir momentan einfällt, dass die Idle-Zeit eine Ungenauigkeit bis zu deinem Update aufweist.

    Beispiel:

    User A ist inaktiv (gesperrter Zustand)
    User B ist angemeldet, allerdings aktuell inaktiv für 20 Sekunden.
    Intervall tritt ein: User A und User B schreiben die Idle-Zeit in die Ini.
    Direkt danach zeigt User B wieder Aktivität.

    In diesem Beispiel würde bis zum nächsten Intervall dennoch in der Ini-Datei stehen, er wäre inaktiv. Abhilfe könnte beispielsweise das Script durch einen zweiten - kürzeren - Intervall auf eine andere Funktion schaffen. Diese Funktion würde dann den zuletzt eingetragenen Idle-Wert mit dem aktuellen vergleichen. Ist der aktuelle kleiner, würde das Ergebnis damit schneller in der Ini-Datei landen.

    Ich hoffe, das Kurzbeispiel reicht bis heute Abend aus. Weiß nicht wann ich zu Hause bin.

    Es gibt Tage, da trete ich nicht ins Fettnäpfchen. Ich falle in die Friteuse.

    2 Mal editiert, zuletzt von Runa (31. März 2016 um 10:12)

  • Das ist nett vielen Dank aber nur kein Stress ;)
    Muss auch kein riesen langer Quelltext sein, einfache Worte a la probier mal dies und jenes sind mir eh lieber. Irgendwie fällt es mir schwer, mich in (fremde) Quelltexte einzudenken bzw. diese zu verstehen, man nehme nur mal die Beispiele aus der AutoIt Hilfe :/