Jump to content

Office Power Saving


Recommended Posts

I'm working on a way to put workstations in hibernation when they're not being used. My office has many remote users, so I also need to wake the workstations as they connect. A separate script will run on the VPN server and send a magic packet to the user's workstation when it sees them connect to the VPN.

So far I've found that the built-in Hibernation ability in Windows XP will hibernate after x minutes of inactivity, and I can successfully wake it with a magic packet or pushing the power button, but it does not hibernate again after another x minutes. My workaround is a script that I intend to install as a service on each workstation that will handle putting idle workstations in hibernation.

Here's the hibernation script. The problem is when the computer wakes up, it wants to hibernate again right away unless I wiggle the mouse. How can I force the idle time (_Timer_GetIdleTime) to reset as the computer wakes from hibernation? I tried setting a variable ($powerstate) and putting in some Sleep time. It will hibernate again when the sleep time is up.

I have more issues to go, but I may be able to tackle them myself once this one is out of the way. Either way, I'll put the whole setup here for the greater good.

#include "Timers.au3"
$powerstate = "on"
$idletime = 1800000; 30 minutes

While 1
    If $powerstate = "hibernating" Then
        $powerstate = "on"
        Sleep(10000)
    EndIf

    If _Timer_GetIdleTime() > $idletime Then
        Hibernate()
    EndIf
WEnd

Func Hibernate()
    $powerstate = "hibernating"
    Shutdown(64)
EndFunc
Link to comment
Share on other sites

Why not just add a mousemove and move it back to the original coordinates?

Looks like that did the trick. Thanks! The sleep time wasn't necessary. Here's what I did:

#include "Timers.au3"
$powerstate = "on"
$idletime = 40000; 40 seconds

While 1
    If $powerstate = "hibernating" Then
        $powerstate = "on"
        $mouseposition = MouseGetPos()
        MouseMove($mouseposition[0],$mouseposition[1],0)
    EndIf

    If _Timer_GetIdleTime() > $idletime Then
        Hibernate()
    EndIf
WEnd

Func Hibernate()
    $powerstate = "hibernating"
    Shutdown(64)
EndFunc
Link to comment
Share on other sites

I remember reading that services don't normally have access to the desktop (aka no manipulation) so you could use the service script to check idle time and call another exe to do the hibernation and mousemove. There's also probably a workaround for manipulating the desktop as a service but I don't know it.

Link to comment
Share on other sites

I remember reading that services don't normally have access to the desktop (aka no manipulation) so you could use the service script to check idle time and call another exe to do the hibernation and mousemove. There's also probably a workaround for manipulating the desktop as a service but I don't know it.

There won't be a desktop if no one is logged in, but I would still like the computer to go into hibernation after x minutes. I'll have to try again tomorrow to see if I can get something to work.
Link to comment
Share on other sites

Try using timer so it hibernates again after xyz minutes...

I'm not sure what you mean. I'm using _Timer_GetIdleTime() now, but it's not resetting when I run the script as a service. I can't use a timer that isn't based on idle time...what if someone's using the computer and it just jumps to hibernate mode while they're working?
Link to comment
Share on other sites

I'm not sure what you mean. I'm using _Timer_GetIdleTime() now, but it's not resetting when I run the script as a service. I can't use a timer that isn't based on idle time...what if someone's using the computer and it just jumps to hibernate mode while they're working?

Well, can't you use two timers? So one will hibernate if someone is idle after e.g. 20 minutes, then you reset it and if computer is idle after 20 minutes then hibernate again.

I can do signature me.

Link to comment
Share on other sites

(Not tested)

Func main()
    $newidletime = $idletime
    While 1
        If _Timer_GetIdleTime() > $idletime Then
            Hibernate()
            $newidletime += $idletime
            ; Wait until system is no longer idle, or if the interval passes again
            While _Timer_GetIdleTime() > $idletime And _Timer_GetTimerID < $newidletime
                Sleep 1000
            WEnd
            If _Timer_GetIdleTime() < $idletime Then $newidletime = $idletime ; No longer idle, reset counter
            ; Else, start hibernate cycle again
        EndIf
    WEnd
EndFunc   ;==>main

[font="Tahoma"]"Tougher than the toughies and smarter than the smarties"[/font]

Link to comment
Share on other sites

(Not tested)

Func main()
    $newidletime = $idletime
    While 1
        If _Timer_GetIdleTime() > $idletime Then
            Hibernate()
            $newidletime += $idletime
            ; Wait until system is no longer idle, or if the interval passes again
            While _Timer_GetIdleTime() > $idletime And _Timer_GetTimerID < $newidletime
                Sleep 1000
            WEnd
            If _Timer_GetIdleTime() < $idletime Then $newidletime = $idletime ; No longer idle, reset counter
            ; Else, start hibernate cycle again
        EndIf
    WEnd
EndFunc   ;==>main
Link to comment
Share on other sites

The parenthesis were omitted. Now it works (based on observation) except when I log out and log in as a different user. Then it won't work unless I restart the service...still working on it. If I log in, out, in as another user, and log again, I have to restart the service every time I wake the computer (using PsService to restart the service)...still working on it...still open to ideas. Same after a restart, leaving it at the login screen: it hibernates the first time, but not afterwards unless I restart the service every time.

Here's the full code I'm using right now:

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Version=Beta
#AutoIt3Wrapper_Change2CUI=y
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
; Example of using service UDF to make an exe possibly runeed as a service
; By Arcker
; 10/09/2008
#include<Service.au3>
#include "Timers.au3"
$powerstate = "on"
$idletime = 25000; 25 seconds
$sServiceName = "Autoit_Service"
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()
    $newidletime = $idletime
    While 1
        If _Timer_GetIdleTime() > $idletime Then
            Hibernate()
            $newidletime = $idletime + _Timer_GetIdleTime()
            ; Wait until system is no longer idle, or if the interval passes again
            While _Timer_GetIdleTime() > $idletime And _Timer_GetIdleTime() < $newidletime
                Sleep 1000
            WEnd
            If _Timer_GetIdleTime() < $idletime Then $newidletime = $idletime ; No longer idle, reset counter
            ; Else, start hibernate cycle again
        EndIf
    WEnd
EndFunc   ;==>main

Func InstallService()
    ConsoleWrite("Installing service, please wait" & @CRLF)
    _Service_Create("", $sServiceName, "Hibernate", '"' & @ScriptFullPath & '"')
    If @error Then
        ConsoleWrite("Problem installing service, Error number is " & @error & @CRLF & " message  : " & _WinAPI_GetLastErrorMessage())
    Else
        ConsoleWrite("Installation of service successful")
    EndIf
    Exit
EndFunc   ;==>InstallService
Func RemoveService()
    _StopService("", $sServiceName)
    _DeleteService("", $sServiceName)
    if not @error then ConsoleWrite("service removed successfully" & @crlf)
    Exit
EndFunc   ;==>RemoveService

Func Msg()
    MsgBox(0,"","OK")
EndFunc

Func Hibernate()
    $powerstate = "hibernating"
    Shutdown(64)
EndFunc
Link to comment
Share on other sites

Is there are way to capture a pre-hibernate and post-hibernate event to trigger something in AutoIT? I found this site http://www.desimonesystems.com/suspendtrigger/index.php that does. It crossed my mind that if I stopped the service right before the hibernate, and restarted it right when it emerged from hibernate that it might solve my problem. Of course, who knows if it would have the same issues with the login screen.

Link to comment
Share on other sites

@sb1920alk

WMI has a "Win32_PowerManagementEvent" class.

This will notify you when a power Status changes as defined in the Advanced Power Management(APM) :

4 Entering Suspend

7 Resume from Suspend

10 Power Status Change

11 OEM Event

18 Resume Automatic

Win32_PowerManagementEvent

Regards,

ptrex

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