Jump to content

Shutdown script when user is inactive


Recommended Posts

Hello,

This is my first AutoIt attempt, so I am sure the script could be coded better :) .

I need a program wich should run as a service to shutdown idle workstations to save power (at a school, around 2600 workstations)

The idea is to put the allowed idletime in a registry or ini file wich the script can read so the allowed idletime can be altered very easely during login process

I have been studying this forum for hours and hours and come up with following script (most of it copied from other authors whom I thanks!) wich isn't all done yet, no registry or ini file and stuff, just the basic to see if it'll work.

Allso a big try-and-error approach.

#NoTrayIcon
#AutoIt3Wrapper_UseUpx=n

Global $MainLog = @ScriptDir & "\services_test2.log"
Global $sServiceName = "AutoitTestService"
Global $iIdleTime = _Timer_GetIdleTime()
Global $IdleStart = _Timer_GetIdleTime()
Global $IdleElapsed = 0
Global $IdleAllowed = 5 * 60
Global $Tick = 0

#include "Services.au3"
#include <Timers.au3> 
#include <WindowsConstants.au3>
#include <StaticConstants.au3>
#include <Misc.au3>

$Servicename = StringLeft(@ScriptName,StringInstr(@ScriptName,".")-1)
$sServiceName = "AutoIt_" & $Servicename

logPrint("script started")
If $cmdline[0] > 0 Then
    Switch $cmdline[1]
        Case "install", "-i", "/i"
            InstallService()
        Case "remove", "-u", "/u", "uninstall"
            RemoveService()
        Case Else
            ConsoleWrite(" - - - Help - - - " & @CRLF)
            ConsoleWrite("params : " & @CRLF)
            ConsoleWrite(" -i : install service" & @CRLF)
            ConsoleWrite(" -u : remove service" & @CRLF)
            ConsoleWrite(" - - - - - - - - " & @CRLF)
            Exit
            ;start service.
    EndSwitch
EndIf
_Service_init($sServiceName)

Func main_init()
    logPrint("main_init. Stop event=" & $service_stop_event)
    $IdleStart = _Timer_GetIdleTime()
    HotKeySet("{F1}", "ResetIdle")
EndFunc   ;==>main_init

Func _Svc_Main()
    main_init()
    logPrint("main start")
    logPrint("main loop. evnt=" & _WinAPI_WaitForSingleObject($service_stop_event, 0))
    While $gServiceStateRunning
        Sleep(30000)  ; 30 seconden niets doen om cpu load te minderen
        $iIdleTime = _Timer_GetIdleTime()
        $IdleElapsed = int(($iIdleTime - $IdleStart) /1000 )
        If $Tick = 0 Then
            $Tick = 1
            logPrint("tick. Idle time = " & $IdleElapsed & "s")
        Else
            $Tick = 0
            logPrint("tock. Idle time = " & $IdleElapsed & "s")
        EndIf       
        If _IsPressed(0x01) Then                                        ; Check if left mouse button is clicked.
            logPrint("mousklick time!!")
            $IdleStart = _Timer_GetIdleTime()
        EndIf

        If $IdleElapsed > $IdleAllowed Then
            logPrint("Shutdown time!!")
            $IdleStart = _Timer_GetIdleTime()
        EndIf
    WEnd
    logPrint("main outer. evnt=" & _WinAPI_WaitForSingleObject($service_stop_event, 0))
    _Service_Cleanup()
    logPrint("main stopped.")
EndFunc   ;==>main

Func ResetIdle()
    logPrint("Reset Idle Timer!!")
    $IdleStart = _Timer_GetIdleTime2()
EndFunc   ;==>ResetIdle
    
Func logPrint($text, $nolog = 0)
    If $nolog Then
        MsgBox(0, "MyService", $text, 1)
    Else
        If Not FileExists($MainLog) Then FileWriteLine($MainLog, "Log created: " & @YEAR & "/" & @MON & "/" & @MDAY & " " & @HOUR & ":" & @MIN & ":" & @SEC)
        FileWriteLine($MainLog, @YEAR & @MON & @MDAY & " " & @HOUR & @MIN & @SEC & " [" & @AutoItPID & "] >> " & $text)
    EndIf
    Return 0
EndFunc   ;==>logPrint

Func InstallService()
    logPrint("InstallService(): Installing service : " & $Servicename & ", please wait")
    _Service_Create($sServiceName, $Servicename, $SERVICE_WIN32_OWN_PROCESS, $SERVICE_AUTO_START, $SERVICE_ERROR_IGNORE,'"' & @ScriptFullPath & '"')
    If @error Then
        logPrint("Problem Installing Service, Error number is " & @error & @CRLF & " message  : " & _WinAPI_GetLastErrorMessage())
        Return 0
    Else
        logPrint("Installation of Service Successful")
    EndIf
    Return 1
    Exit
EndFunc   ;==>InstallService


Func RemoveService()
    _Service_Stop($sServiceName)
    _Service_Delete($sServiceName)
    If Not @error Then logPrint("RemoveService(): service :" & $Servicename & " removed successfully" & @CRLF)
    Exit
EndFunc   ;==>RemoveService

Good news first

The script does run as a service, it installs and uninstalls good

The script will allso log perfectly, I know hereby that there seem to be no syntax error :)

A log:

20110307 212530 [2924] >> script started
20110307 212530 [2924] >> InstallService(): Installing service : IdleShutdown, please wait
20110307 212530 [2924] >> Installation of Service Successful
20110307 212541 [2920] >> script started
20110307 212541 [2920] >> main_init. Stop event=0x000001CC
20110307 212541 [2920] >> main start
20110307 212541 [2920] >> main loop. evnt=258
20110307 212611 [2920] >> tick. Idle time = 30s
20110307 212641 [2920] >> tock. Idle time = 60s
20110307 212711 [2920] >> tick. Idle time = 90s
20110307 212741 [2920] >> tock. Idle time = 120s
20110307 212811 [2920] >> tick. Idle time = 150s
20110307 212841 [2920] >> tock. Idle time = 180s
20110307 212911 [2920] >> tick. Idle time = 210s
20110307 212941 [2920] >> tock. Idle time = 240s
20110307 213012 [2920] >> tick. Idle time = 270s
20110307 213042 [2920] >> tock. Idle time = 300s
20110307 213112 [2920] >> tick. Idle time = 330s
20110307 213112 [2920] >> Shutdown time!!
20110307 213142 [2920] >> tock. Idle time = 30s
20110307 213212 [2920] >> tick. Idle time = 60s
20110307 213242 [2920] >> tock. Idle time = 90s
20110307 213305 [2580] >> script started
20110307 213305 [2580] >> RemoveService(): service :IdleShutdown removed successfully

I have tried _Timer_GetIdleTime(), but that timer doesn't reset when mouse/keyboard is used

I have tapped the F1 key and the left mouse key wich should reset the counter: $IdleStart

But that doesn't happen.

I think this has to do with the fact that the script runs as the user: system .

I have searched the forum for shutdown timer, idletime, powersaving etc. But didn't found the solution.

Compiled it with and without the option Console

How can I make this work?

Thanks in advance.

John

Link to comment
Share on other sites

  • Developers

Welcome John,

Just out of curiosity: Why not use the build in power saving options for this?

Jos

SciTE4AutoIt3 Full installer Download page   - Beta files       Read before posting     How to post scriptsource   Forum etiquette  Forum Rules 
 
Live for the present,
Dream of the future,
Learn from the past.
  :)

Link to comment
Share on other sites

Not using built in powersaving options cause logged in user should overwrite normal behaviour

Times are debatable :)

If pc's turned on and not used (no login) shutdown within 30 minutes

If pc's last login is a student AND not used shutdown within 50 minutes

If logon is a student and not used for 50 minutes, shutdown

If login is a tutor and not used shutdown after 150 minutes (might have two non teaching hours)

If login is administrative personel and not used after 120 minutes shutdown

If pc is a tutor workplace (pc's placed so tutors can check mail etc) if turned on and time of day is after 15:00 and idle for 30 minutes shutdown (thus keeping pc powered on)

There are some more if's but this give you an idea. Allso the ifs might differ per situation / building etc.

In stead of shutdown a logoff might be needed, freeing up locked workstations.

Allso script should finally log usage of pc, idle vs active time, who is logged on, maybe even log programs used, we have some programs teachers claim they need, wich sysops think they are not used that much (license costs)

This way the usage of pc's could be charted.

The users logging on are allready logged at login/off times, next to it charting idle/active usage and wich programm is used could benefit (system)management.

At the moment we run a script to shutdown everything (except servers etc) at 19:00 hours.

If we could shutdown earlier we might save on energycosts.

(2600 pc's energy cost around 400 euro (550ish dollar) per day, there are around 200 schooldays a year - total 80000euro per year, even a small 10% saves 800euro (1100ish dollar).

John

Link to comment
Share on other sites

  • Developers
:) Trying to think whether this is possible or not, because you are looking for running the script as a service and want to detect Keyboard and Mouse actions.

SciTE4AutoIt3 Full installer Download page   - Beta files       Read before posting     How to post scriptsource   Forum etiquette  Forum Rules 
 
Live for the present,
Dream of the future,
Learn from the past.
  :)

Link to comment
Share on other sites

I see there lies the problem, detecting mouse/keyboard activity when running as a service (with or without logged user)

Could the following idea be reachable?

Use above script as an inactivity timer when there is no logged on user, when there is a user logged on another script could kick in wich takes it from there (with _Timer_GetIdleTime() for example)

The above script running as a service, should be doing something like (pseudocode) :

init:
while 1
  if check if a user is logged in = false {
      countdowntimerfunction
      if countdowntimer reach threshold, shutdown
  } else {
      there is a logged in user, reset countdowntimers
      ; do nothing more, since user activated script takes it from here
      ; maybe watchdog that user activated script?
  }
wend

This leave me with the question, how to detect if a user is logged in when running the script as a service as user System?

Searched this knowledgable forum gave me this : at the end it says twisted but it works.

Maybe there is a less twisted way?

If the user System is the trouble, services can allso be run with other usercredentials, but then it will be more like a user then a system service.

Or is there a better way of achieving my goals?

T.i.a.

John

Edited by john102749
Link to comment
Share on other sites

  • Developers

You probably can convert the vbs code posted by somebody in our forums to detect the logged-on userids:

I could imagine running a script at logon time that communicates to the Service_script via the Send Message WM_COPYDATA option. (Examples available in the forums as well)

Sounds like a FUN project to work on. :)

Edited by Jos

SciTE4AutoIt3 Full installer Download page   - Beta files       Read before posting     How to post scriptsource   Forum etiquette  Forum Rules 
 
Live for the present,
Dream of the future,
Learn from the past.
  :)

Link to comment
Share on other sites

Sounds like a FUN project to work on. :)

Yups, soud as fun to me too, only thing is, I am not a programmer, more an allround ITman, doing IT since 1981, and am what older so new stuff settle harder in my brains much slower.

Did autoit many years ago. Started again for this job.

My final goal would be something wich does a few things;

1 - powersavings, see above, powersavings is moneysaving when dealing with this amount of pc's

2 - check for active/idletime per user/pc

3 - check for activity on programms used, when first/last etc

4 - check for new programs started on a pc so illegal programms can be killed

whatever else comes to mind

Am coördinating a group of systemengineers in a school environment.

As coördinator I must look at costs, since Dutch government is starting to spend less, we need to do with less.

Am open to good ideas or leads... even help :)

John

Link to comment
Share on other sites

  • Developers

Yups, soud as fun to me too, only thing is, I am not a programmer, more an allround ITman, doing IT since 1981, and am what older so new stuff settle harder in my brains much slower.

Lets shake hands... started in 79 in whatever they called it in those days. :)

..and Dutch too...

Edited by Jos

SciTE4AutoIt3 Full installer Download page   - Beta files       Read before posting     How to post scriptsource   Forum etiquette  Forum Rules 
 
Live for the present,
Dream of the future,
Learn from the past.
  :)

Link to comment
Share on other sites

Ok, pursuing 2 progs

1 System watch

If no logged on user exists

Count Idletime

If Idletime > allowed time, shutdown

If user logged on exists

Count Usertime

#NoTrayIcon
#AutoIt3Wrapper_UseUpx=n

Global $sServiceName = StringLeft(@ScriptName,StringInstr(@ScriptName,".")-1)
Global $MainLog = @ScriptDir & "\"& $sServiceName & "_test.log"
Global $TimeStarted = TimerInit()
Global $TimeUserStart = TimerInit()
Global $TimeIdleStart = TimerInit()
Global $CurrentTime = ""
Global $TotalUser = 0
Global $TotalIdle = 0
Global $IdleAllowed = 60 * 10  ; Amount of minutes before shutdown is initiated!
Global $Tick = 0
Global $Klick = 0
Global $Username = ""

#include "Services.au3"
#include <Timers.au3> 

logPrint("script started")

If $cmdline[0] > 0 Then
    Switch $cmdline[1]
        Case "install", "-i", "/i"
            InstallService()
        Case "remove", "-u", "/u", "uninstall"
            RemoveService()
        Case Else
            ConsoleWrite(" - - - Help - - - " & @CRLF)
            ConsoleWrite("params : " & @CRLF)
            ConsoleWrite(" -i : install service" & @CRLF)
            ConsoleWrite(" -u : remove service" & @CRLF)
            ConsoleWrite(" - - - - - - - - " & @CRLF)
            Exit
            ;start service.
    EndSwitch
EndIf

_Service_init($sServiceName)

Func _Svc_Main()   ; This is the main code wich will be run when this program is a service!!
    LogPrint("main started.")
    
    ; Reset timers to 0
    $TimeStarted = TimerInit()
    $TimeUserStart = TimerInit()
    $TimeIdleStart = TimerInit()

    While $gServiceStateRunning
    
        GetUser()

        If $Username <> "" Then
            If $Klick = 0 Then     ; User is new
                $Klick = 1
                ResetUser("User-new! : " & $Username & " - Idle time :" & Floor(TimerDiff($TimeIdleStart)/1000) & "s")
                $TotalIdle += Floor(TimerDiff($TimeIdleStart)/1000)
            EndIf
        Else
            If $Klick = 1 Then   ; user has left
                $Klick = 0
                ResetIdle("Userleft! : " & $Username & " - Time spent :" & Floor(TimerDiff($TimeUserStart)/1000) & "s")
                $TotalUser += Floor(TimerDiff($TimeUserStart)/1000)
            EndIf
            
            If $IdleAllowed < TimerDiff($TimeIdleStart)/1000 Then
                logPrint("Shutdown time!!") ; Here comes code to shut it down!
            EndIf
        EndIf
        
        $Tick += 1

        If $Tick > 0 Then   ; Once every x * 10 seconds write to log, heartbeat
            $Tick = 0
            If $Klick = 0 Then ; No user
                $CurrentTime =  "Current Idle = " & Floor(TimerDiff($TimeIdleStart)/1000)
            Else    
                $CurrentTime =  "Current User = " & Floor(TimerDiff($TimeUserStart)/1000)
            EndIf           
            logPrint("Heartbeat. Total time = " & Floor(TimerDiff($TimeStarted)/1000) & "s - Total Idle = " & $TotalIdle & "s - Total User = " & $TotalUser & "s - " & $CurrentTime & "s")
        EndIf       
        
        Sleep(10000)  ; 10 seconds doing nothing, don't overload cpu!
        
    WEnd
    _Service_Cleanup()
    logPrint("main stopped.")
EndFunc   ;==>main

Func GetUser()
    $objWMIService = Objget("winmgmts:\\localhost\root\cimv2")
    $colComputer = $objWMIService.ExecQuery("Select * from Win32_ComputerSystem")
    If IsObj($colComputer) Then
        For $objComputer In $colComputer
            $Username = $objComputer.UserName
        Next
    Else
        $Username = "" 
    EndIf
EndFunc     ;==>GetUser

Func ResetIdle( $Message = "" )
    logPrint("Reset IdleTimer!! " & $Message )
    $TimeIdleStart = TimerInit()
EndFunc   ;==>ResetIdle

Func ResetUser( $Message = "" )
    logPrint("Reset UserTimer!! " & $Message )
    $TimeUserStart = TimerInit()
EndFunc   ;==>ResetIdle
    
Func logPrint($text, $nolog = 0)
    If $nolog Then
        MsgBox(0, "MyService", $text, 1)
    Else
        If Not FileExists($MainLog) Then FileWriteLine($MainLog, "Log created: " & @YEAR & "/" & @MON & "/" & @MDAY & " " & @HOUR & ":" & @MIN & ":" & @SEC)
        FileWriteLine($MainLog, @YEAR & @MON & @MDAY & " " & @HOUR & @MIN & @SEC & " [" & @AutoItPID & "] >> " & $text)
    EndIf
    Return 0
EndFunc   ;==>logPrint

Func InstallService()
    logPrint("InstallService(): Installing service : " & $sServicename & ", please wait")
    _Service_Create($sServiceName, $sServicename, $SERVICE_WIN32_OWN_PROCESS, $SERVICE_AUTO_START, $SERVICE_ERROR_IGNORE,'"' & @ScriptFullPath & '"')
    If @error Then
        logPrint("Problem Installing Service, Error number is " & @error & @CRLF & " message  : " & _WinAPI_GetLastErrorMessage())
        Return 0
    Else
        logPrint("Installation of Service Successful")
    EndIf
    Return 1
    Exit
EndFunc   ;==>InstallService

Func RemoveService()
    logPrint("UnInstallService(): UnInstalling service : " & $sServicename & ", please wait")
    _Service_Stop($sServiceName)
    _Service_Delete($sServiceName)
    If Not @error Then logPrint("RemoveService(): service :" & $sServicename & " removed successfully" & @CRLF)
    Exit
EndFunc   ;==>RemoveService

Short instructions : compile as console, install as service from command prompt with <progname -i>

then start service, sc start <progname>

uninstall as service, kill process in taskmanager, then from command prompt <progname -u>

Log:

Log created: 2011/03/10 15:13:35
20110310 151335 [1396] >> script started
20110310 151335 [1396] >> InstallService(): Installing service : IdleShutdown, please wait
20110310 151335 [1396] >> Installation of Service Successful
20110310 151343 [2988] >> script started
20110310 151343 [2988] >> main started.
20110310 151343 [2988] >> Reset UserTimer!! User-new! : PC-2011\John - Idle time :0s
20110310 151343 [2988] >> Heartbeat. Total time = 0s - Total Idle = 0s - Total User = 0s - Current User = 0s
20110310 151353 [2988] >> Heartbeat. Total time = 10s - Total Idle = 0s - Total User = 0s - Current User = 10s
20110310 151403 [2988] >> Heartbeat. Total time = 20s - Total Idle = 0s - Total User = 0s - Current User = 20s
20110310 151413 [2988] >> Heartbeat. Total time = 30s - Total Idle = 0s - Total User = 0s - Current User = 30s
20110310 151423 [2988] >> Heartbeat. Total time = 40s - Total Idle = 0s - Total User = 0s - Current User = 40s
20110310 151433 [2988] >> Heartbeat. Total time = 50s - Total Idle = 0s - Total User = 0s - Current User = 50s
20110310 151443 [2988] >> Reset IdleTimer!! Userleft! :  - Time spent :60s
20110310 151443 [2988] >> Heartbeat. Total time = 60s - Total Idle = 0s - Total User = 60s - Current Idle = 0s
20110310 151453 [2988] >> Heartbeat. Total time = 70s - Total Idle = 0s - Total User = 60s - Current Idle = 10s
20110310 151503 [2988] >> Heartbeat. Total time = 80s - Total Idle = 0s - Total User = 60s - Current Idle = 20s
20110310 151513 [2988] >> Reset UserTimer!! User-new! : PC-2011\John - Idle time :30s
20110310 151513 [2988] >> Heartbeat. Total time = 90s - Total Idle = 30s - Total User = 60s - Current User = 0s
20110310 151523 [2988] >> Heartbeat. Total time = 100s - Total Idle = 30s - Total User = 60s - Current User = 10s
20110310 151533 [2988] >> Heartbeat. Total time = 110s - Total Idle = 30s - Total User = 60s - Current User = 20s
20110310 151543 [2988] >> Heartbeat. Total time = 120s - Total Idle = 30s - Total User = 60s - Current User = 30s
20110310 151553 [2988] >> Heartbeat. Total time = 130s - Total Idle = 30s - Total User = 60s - Current User = 40s
20110310 151603 [2988] >> Reset IdleTimer!! Userleft! :  - Time spent :50s
20110310 151603 [2988] >> Heartbeat. Total time = 140s - Total Idle = 30s - Total User = 110s - Current Idle = 0s
20110310 151613 [2988] >> Heartbeat. Total time = 150s - Total Idle = 30s - Total User = 110s - Current Idle = 10s
20110310 151624 [2988] >> Reset UserTimer!! User-new! : PC-2011\John - Idle time :20s
20110310 151624 [2988] >> Heartbeat. Total time = 160s - Total Idle = 50s - Total User = 110s - Current User = 0s
20110310 151634 [2988] >> Heartbeat. Total time = 170s - Total Idle = 50s - Total User = 110s - Current User = 10s
20110310 151644 [2988] >> Heartbeat. Total time = 180s - Total Idle = 50s - Total User = 110s - Current User = 20s
20110310 151654 [2988] >> Heartbeat. Total time = 190s - Total Idle = 50s - Total User = 110s - Current User = 30s
20110310 151704 [2988] >> Heartbeat. Total time = 200s - Total Idle = 50s - Total User = 110s - Current User = 40s

So far so good :)

Am happy with it since it achieves my goal.

A point of approvement for wich I need some help

The main loop holds for 10 seconds every loop, when a user logs off or system shutdown system might wait for the 10 seconds loop

One solution could be to lower the 10 seconds delay but that will create more cpu stress

Is there a better way of doing that?

Could this programm be improved?

Now off to next part, the userprog

John

Edited by john102749
Link to comment
Share on other sites

If you want to check some user activity on the PC, you can use PixelChecksum command...

Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.
Link to comment
Share on other sites

Next version

Added SetProcessShutdownParameters - It will now detect user loggoff before script stops

Changed Sleep time to 1 sec. Responds faster when there is a shutdown going on

#NoTrayIcon
#AutoIt3Wrapper_UseUpx=n

#include "Services.au3"
#include <Timers.au3> 

Global $sServiceName = StringLeft(@ScriptName,StringInstr(@ScriptName,".")-1)
Global $MainLog = @ScriptDir & "\"& $sServiceName & "_test.log"
Global $TimeStarted = TimerInit()
Global $TimeUserStart = TimerInit()
Global $TimeIdleStart = TimerInit()
Global $CurrentTime = "0"
Global $TotalUser = 0
Global $TotalIdle = 0
Global $IdleAllowed = 60 * 10  ; Amount of minutes before shutdown is initiated!
Global $Tick = 0
Global $Klick = 0
Global $Username = ""
Global $b_ShutdownInitiated = False

logPrint("script started")

If $cmdline[0] > 0 Then
    Switch $cmdline[1]
        Case "install", "-i", "/i"
            InstallService()
        Case "remove", "-u", "/u", "uninstall"
            RemoveService()
        Case Else
            ConsoleWrite(" - - - Help - - - " & @CRLF)
            ConsoleWrite("params : " & @CRLF)
            ConsoleWrite(" -i : install service" & @CRLF)
            ConsoleWrite(" -u : remove service" & @CRLF)
            ConsoleWrite(" - - - - - - - - " & @CRLF)
            Exit
            ;start service.
    EndSwitch
EndIf

_Service_init($sServiceName)

; set highest notification level, user will be logged off before this script ends
If Not _SetProcessShutdownParameters(0xFFF) Then ; MSDN says maximum is 0x4FF, but it worked for me
    If Not _SetProcessShutdownParameters(0x4FF) Then ; MSDN says this is reserved for System, but worked for me
        _SetProcessShutdownParameters(0x3FF) ; highest not reserved number, if everything else does not work
    EndIf
EndIf

Func _Svc_Main()   ; This is the main code wich will be run when this program is a service by _service_init !!
    LogPrint("main started.")
    
    ; Reset timers
    $TimeStarted = TimerInit()
    $TimeUserStart = TimerInit()
    $TimeIdleStart = TimerInit()
    
    While $gServiceStateRunning
    
        GetUser()

        If $Username <> "" Then                     ; There is a username known
            If $Klick = 0 Then                  ; User is new
                $Klick = 1
                $TotalIdle += Floor(TimerDiff($TimeIdleStart)/1000)
                ResetUser("User-new.: " & $Username & " - Total time = " & Floor(TimerDiff($TimeStarted)/1000) & "s - Total Idle = " & $TotalIdle & "s - Total User = " & $TotalUser & "s - " & $CurrentTime & "s")
            EndIf
        Else                                ; No username known
            If $Klick = 1 Then                      ; There was a user, user must has left
                $Klick = 0
                $TotalUser += Floor(TimerDiff($TimeUserStart)/1000)
                ResetIdle("Userleft. Total time = " & Floor(TimerDiff($TimeStarted)/1000) & "s - Total Idle = " & $TotalIdle & "s - Total User = " & $TotalUser & "s - " & $CurrentTime & "s")
            EndIf
            
            If $IdleAllowed < TimerDiff($TimeIdleStart)/1000 Then
                logPrint("Shutdown time!!")             ; Here comes code to shut it down!
            EndIf
        EndIf
        
        $Tick += 1

        If $Tick > 60 Then                          ; Once every x * 1 second write to log, heartbeat
            $Tick = 0
            If $Klick = 0 Then                  ; No user
                $CurrentTime =  "Current Idle = " & Floor(TimerDiff($TimeIdleStart)/1000)
            Else    
                $CurrentTime =  "Current User = " & Floor(TimerDiff($TimeUserStart)/1000)
            EndIf           
            logPrint("Heartbeat. Total time = " & Floor(TimerDiff($TimeStarted)/1000) & "s - Total Idle = " & $TotalIdle & "s - Total User = " & $TotalUser & "s - " & $CurrentTime & "s")
        EndIf       
        
        Sleep(1000)                             ; 1 seconds doing nothing, don't overload cpu!
        
    WEnd
    _Service_Cleanup()
    logPrint("main stopped.")
EndFunc   ;==>main

Func GetUser()
    $objWMIService = Objget("winmgmts:\\localhost\root\cimv2")
    $colComputer = $objWMIService.ExecQuery("Select * from Win32_ComputerSystem")
    If IsObj($colComputer) Then
        For $objComputer In $colComputer
            $Username = $objComputer.UserName
        Next
    Else
        $Username = "" 
    EndIf
EndFunc     ;==>GetUser

Func ResetIdle( $Message = "" )
    logPrint("Reset IdleTimer!! " & $Message )
    $TimeIdleStart = TimerInit()
EndFunc   ;==>ResetIdle

Func ResetUser( $Message = "" )
    logPrint("Reset UserTimer!! " & $Message )
    $TimeUserStart = TimerInit()
EndFunc   ;==>ResetIdle
    
Func logPrint($text, $nolog = 0)
    If $nolog Then
        MsgBox(0, "MyService", $text, 1)
    Else
        If Not FileExists($MainLog) Then FileWriteLine($MainLog, "Log created: " & @YEAR & "/" & @MON & "/" & @MDAY & " " & @HOUR & ":" & @MIN & ":" & @SEC)
        FileWriteLine($MainLog, @YEAR & @MON & @MDAY & " " & @HOUR & @MIN & @SEC & " [" & @AutoItPID & "] >> " & $text)
    EndIf
    Return 0
EndFunc   ;==>logPrint

Func InstallService()
    logPrint("InstallService(): Installing service : " & $sServicename & ", please wait")
    _Service_Create($sServiceName, $sServicename, $SERVICE_WIN32_OWN_PROCESS, $SERVICE_AUTO_START, $SERVICE_ERROR_IGNORE,'"' & @ScriptFullPath & '"')
    If @error Then
        logPrint("Problem Installing Service, Error number is " & @error & @CRLF & " message  : " & _WinAPI_GetLastErrorMessage())
        Return 0
    Else
        logPrint("Installation of Service Successful")
    EndIf
    Return 1
    Exit
EndFunc   ;==>InstallService

Func RemoveService()
    logPrint("UnInstallService(): UnInstalling service : " & $sServicename & ", please wait")
    _Service_Stop($sServiceName)
    _Service_Delete($sServiceName)
    If Not @error Then logPrint("RemoveService(): service :" & $sServicename & " removed successfully" & @CRLF)
    Exit
EndFunc   ;==>RemoveService

Func _SetProcessShutdownParameters($dwLevel, $dwFlags=0)
    ; http://msdn.microsoft.com/en-us/library/ms686227%28VS.85%29.aspx
    ; Prog@ndy
    Local $aResult = DllCall("Kernel32.dll", "int", "SetProcessShutdownParameters", "dword", $dwLevel, "dword", $dwFlags)
    If @error Then Return SetError(1,0,0)
    Return $aResult[0]
EndFunc ;==>_SetProcessShutdownParameters

One thing I can't achieve to do is intercept shutdown signal

tried WM_QUERYENDSESSION and WM_ENDSESSION (see for examples)

I can't get it to work when running a service as system on windows7 64 bit.

Ahh well, need to live with that :)

Off to the next part, detect activewindows when user is logged on, wil be another script.

John

Link to comment
Share on other sites

  • 1 month later...

John - interesting idea.

Given what you are trying to do (ensure machines get shut down, and prevent users from disabling this functionality) I think there are better ways to go about this.

Use the native shutdown functionality in the screensaver. Establish this in a System Policy. Have your service run a script to re-enable this policy every 5 minutes. Hell, you may be able to just enable the system policy - even local admins can be prevented from touching local policy provide it's configured correctly.

That's the approach I'd take. Policy is nice because it can be re-enforced on a box.

Link to comment
Share on other sites

I need this prog cause of variable idletimes.

Prog will be used to start measuring idletime and kicks in shutdown after 90 minutes, after noon it will shutdown after 50 minutes,

and shutdown after 15 minutes or so when it is after 16:00 hours

There is no policy, yet, wich can do that.

First prog will be used to measure benefits of using such a prog. Am learning autoits way of mysql direct write or posting to a webform so measurements can be made per school. These measurements will then be used to set the three idletimes (90 - 50 and 15 minutes)

John

Link to comment
Share on other sites

  • 2 years later...

Nice project, since last post...

I am looking for same things, and i found same problemes and same structure, but with three process:

- one for machine idltime (if someone logged on or not) and display state (on or off duration)

- one for user idltime

- and one for logging time passed in working mode, standby mode, for power usage calcul (green it).

Then those process logs data in window event log, and a syslog agent send it to a server to centralise data. the next goal is a php mysql application to make reports.

I am not yet finished, always in test, and you ?

Link to comment
Share on other sites

  • Moderators

steph74,

You appear to have 2 accounts - this one and greenman03. I assume this is an oversight on your part and I would be happy to merge them - which account would you like to keep? :huh:

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...