Jump to content
Sign in to follow this  
User3D

How to check if there is someone working?

Recommended Posts

User3D

Hello,

I made some scripts that are launched by Task Scheduler. At the end I'd like to shutdown the computer, but ONLY and ONLY if there is no user working. I have no idea, how to check if there is anyone connected in order not to shutdown the computer. Do you know how to do that?

Thank you in advance for your help

Best Regards

User3D

Share this post


Link to post
Share on other sites
guinness

I would use the function by JohnOne, but for the sake of someone coming across this in the future and who use WinAPIEx.au3, then you also have _WinAPI_GetIdleTime.


UDF List:

 
_AdapterConnections()_AlwaysRun()_AppMon()_AppMonEx()_ArrayFilter/_ArrayReduce_BinaryBin()_CheckMsgBox()_CmdLineRaw()_ContextMenu()_ConvertLHWebColor()/_ConvertSHWebColor()_DesktopDimensions()_DisplayPassword()_DotNet_Load()/_DotNet_Unload()_Fibonacci()_FileCompare()_FileCompareContents()_FileNameByHandle()_FilePrefix/SRE()_FindInFile()_GetBackgroundColor()/_SetBackgroundColor()_GetConrolID()_GetCtrlClass()_GetDirectoryFormat()_GetDriveMediaType()_GetFilename()/_GetFilenameExt()_GetHardwareID()_GetIP()_GetIP_Country()_GetOSLanguage()_GetSavedSource()_GetStringSize()_GetSystemPaths()_GetURLImage()_GIFImage()_GoogleWeather()_GUICtrlCreateGroup()_GUICtrlListBox_CreateArray()_GUICtrlListView_CreateArray()_GUICtrlListView_SaveCSV()_GUICtrlListView_SaveHTML()_GUICtrlListView_SaveTxt()_GUICtrlListView_SaveXML()_GUICtrlMenu_Recent()_GUICtrlMenu_SetItemImage()_GUICtrlTreeView_CreateArray()_GUIDisable()_GUIImageList_SetIconFromHandle()_GUIRegisterMsg()_GUISetIcon()_Icon_Clear()/_Icon_Set()_IdleTime()_InetGet()_InetGetGUI()_InetGetProgress()_IPDetails()_IsFileOlder()_IsGUID()_IsHex()_IsPalindrome()_IsRegKey()_IsStringRegExp()_IsSystemDrive()_IsUPX()_IsValidType()_IsWebColor()_Language()_Log()_MicrosoftInternetConnectivity()_MSDNDataType()_PathFull/GetRelative/Split()_PathSplitEx()_PrintFromArray()_ProgressSetMarquee()_ReDim()_RockPaperScissors()/_RockPaperScissorsLizardSpock()_ScrollingCredits_SelfDelete()_SelfRename()_SelfUpdate()_SendTo()_ShellAll()_ShellFile()_ShellFolder()_SingletonHWID()_SingletonPID()_Startup()_StringCompact()_StringIsValid()_StringRegExpMetaCharacters()_StringReplaceWholeWord()_StringStripChars()_Temperature()_TrialPeriod()_UKToUSDate()/_USToUKDate()_WinAPI_Create_CTL_CODE()_WinAPI_CreateGUID()_WMIDateStringToDate()/_DateToWMIDateString()Au3 script parsingAutoIt SearchAutoIt3 PortableAutoIt3WrapperToPragmaAutoItWinGetTitle()/AutoItWinSetTitle()CodingDirToHTML5FileInstallrFileReadLastChars()GeoIP databaseGUI - Only Close ButtonGUI ExamplesGUICtrlDeleteImage()GUICtrlGetBkColor()GUICtrlGetStyle()GUIEventsGUIGetBkColor()Int_Parse() & Int_TryParse()IsISBN()LockFile()Mapping CtrlIDsOOP in AutoItParseHeadersToSciTE()PasswordValidPasteBinPosts Per DayPreExpandProtect GlobalsQueue()Resource UpdateResourcesExSciTE JumpSettings INISHELLHOOKShunting-YardSignature CreatorStack()Stopwatch()StringAddLF()/StringStripLF()StringEOLToCRLF()VSCROLLWM_COPYDATAMore Examples...

Updated: 22/04/2018

Share this post


Link to post
Share on other sites
kylomas

Simple example using _winapi_getidletime(). Note - this only gets input idle time (normally KB and mouse)

#include <Constants.au3>
#include <winapiex.au3>

#AutoIt3Wrapper_Add_Constants=n

HotKeySet("{ESC}", "_exit")

local $count_down = 5 * 60 * 1000  ; 5 mins in millisecs
local $old_idle_time = 0, $secs, $mins, $diff

while 1

    sleep(1000) ; idle for a sec

    if $old_idle_time > _winapi_getidletime() then $old_idle_time = _winapi_getidletime()

    if _winapi_getidletime() > $count_down then
        ;
        msgbox($mb_ok,'Armageddon','Do your thing here')
        exit
        ;
    endif

    $diff = int( $count_down - _winapi_getidletime() )

    $secs = int(Mod($diff, 60000)/1000)
    $mins = Mod(Int($diff / 60000), 60)

    traytip('',$mins & ' minutes and ' & $secs & ' seconds to shutdown',0,0)

wend

func _exit()

    Exit

endfunc

Forum Rules         Procedure for posting code

"I like pigs.  Dogs look up to us.  Cats look down on us.  Pigs treat us as equals."

- Sir Winston Churchill

Share this post


Link to post
Share on other sites
kylomas

User3D,

how to check if there is anyone connected in order not to shutdown the computer

If by "connected" you mean logged on to another account or through RDP/Terminal Services then this might help.

(expanded countdown time to include hours)

#include <Constants.au3>
#include <winapiex.au3>
#include <array.au3>

#AutoIt3Wrapper_Add_Constants=n

HotKeySet("{ESC}", "_exit")

Local $count_down = 5 * (60 * 1000)     ; 5 minutes in milliseconds
Local $old_idle_time = 0, $secs, $mins, $diff, $hours

While 1

    $diff = Int($count_down - _winapi_getidletime())

    $secs = Int(Mod($diff, 60000) / 1000)
    $mins = Mod(Int($diff / 60000), 60)
    $hours = Int(($diff / 60000) / 60)

    TrayTip('', $hours & ' hours ' & $mins & ' minutes and ' & $secs & ' seconds to shutdown', 0, 0)

    Sleep(1000) ; idle for a sec

    If $old_idle_time > _winapi_getidletime() Then $old_idle_time = _winapi_getidletime()

    If _winapi_getidletime() > $count_down Then

        ; check for other active users

        $aRet = get_users()

        for $1 = 0 to ubound($aRet) - 1
            if $aRet[$1][0] <> @UserName and $aRet[$1][0] <> '' then
                if msgbox($mb_okcancel,'*** Warning ***',$aRet[$1][0] & ' is logged on' & ' from ' & $aRet[$1][1] & @lf &@lf & _
                            'Click "Cancel" to cancel shutdown') = 2 then exit
            endif
        Next

        ; no other users and idle time reached

        MsgBox($mb_ok, 'Armageddon', 'Do your thing here')

        Exit

    EndIf

WEnd

Func _exit()

    Exit

EndFunc   ;==>_exit

Func get_users()

    Local $strComputer = "localhost", $aLoggedOn[1][2], $iEle = 0
    $objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\root\CIMV2")

    $colSessions = $objWMIService.ExecQuery _
            ("Select * from Win32_LogonSession Where LogonType = 2 OR LogonType = 10")

    For $objSession In $colSessions
        $colList = $objWMIService.ExecQuery("Associators of " _
                 & "{Win32_LogonSession.LogonId=" & $objSession.LogonId & "} " _
                 & "Where AssocClass=Win32_LoggedOnUser Role=Dependent")
        For $objItem In $colList
            $aLoggedOn[$iEle][0] = $objItem.Name
            If $objSession.LogonType = 2 Then
                $aLoggedOn[$iEle][1] = 'Console'
            Else
                $aLoggedOn[$iEle][1] = 'RDP / Terminal Services'
            EndIf
            $iEle += 1
            ReDim $aLoggedOn[UBound($aLoggedOn) + 1][2]
        Next
    Next

    return $aLoggedOn

EndFunc   ;==>get_users

kylomas


Forum Rules         Procedure for posting code

"I like pigs.  Dogs look up to us.  Cats look down on us.  Pigs treat us as equals."

- Sir Winston Churchill

Share this post


Link to post
Share on other sites
BrewManNH

Wouldn't using getidletimer just tell you the last time the mouse or keyboard was used, and not if anyone is still logged in? Wouldn't it be better to use WMI to tell if there was someone still logged on to the computer? I don't know what GetIdleTimer shows if there's no one logged on, but WMI will tell you for sure if anyone is.

; code derived from AU3Scriptomatic output
$wbemFlagReturnImmediately = 0x10
$wbemFlagForwardOnly = 0x20
$colItems = ""
$strComputer = "localhost"

$Output = ""
$Output = $Output & "Computer: " & $strComputer & @CRLF
$Output = $Output & "==========================================" & @CRLF
$objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\ROOT\CIMV2")
$colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_ComputerSystem", "WQL", _
        $wbemFlagReturnImmediately + $wbemFlagForwardOnly)

If IsObj($colItems) Then
    For $objItem In $colItems
        $Output = $Output & "UserName: " & $objItem.UserName & @CRLF
        If MsgBox(1, "WMI Output", $Output) = 2 Then ExitLoop
        $Output = ""
    Next
Else
    MsgBox(0, "WMI Output", "No WMI Objects Found for class: " & "Win32_ComputerSystem")
EndIf


Func WMIDateStringToDate($dtmDate)

    Return (StringMid($dtmDate, 5, 2) & "/" & _
            StringMid($dtmDate, 7, 2) & "/" & StringLeft($dtmDate, 4) _
             & " " & StringMid($dtmDate, 9, 2) & ":" & StringMid($dtmDate, 11, 2) & ":" & StringMid($dtmDate, 13, 2))
EndFunc   ;==>WMIDateStringToDate


If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Share this post


Link to post
Share on other sites
kylomas

@BrewmanNH - Yes, that's why I posted another solution, _winapi_getidletime did not really answer the OP's question...

kylomas


Forum Rules         Procedure for posting code

"I like pigs.  Dogs look up to us.  Cats look down on us.  Pigs treat us as equals."

- Sir Winston Churchill

Share this post


Link to post
Share on other sites
BrewManNH

Oops, sorry, I was updating the script I posted and hadn't noticed the new post by you. Great minds think alike I guess. :D


If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Share this post


Link to post
Share on other sites
kylomas

"I resemble that remark!"


Forum Rules         Procedure for posting code

"I like pigs.  Dogs look up to us.  Cats look down on us.  Pigs treat us as equals."

- Sir Winston Churchill

Share this post


Link to post
Share on other sites
User3D

Hello,

Thank you for your answers.

After reading 3 fiirst answers, I used _Timer_GetIdleTime() function as I didn’t find the description of _WinAPI_GetIdleTime function. Using _Timer_GetIdleTime(), I made some scripts, which I use within .bat one launched every night. My goal was to shut the computer only and only if it is not in use. The solution I put in place answers partially my request, as it will not shut the computer is someone stops working when the night task is in progress. It will avoid shutting the computer if someone logs-in during the night task execution. Below you can find the scripts (.au3 with .bat put within as comment) if someone is interested in.

Probably, the best approach is to compile .au3 in order to get .exe file, but I haven’t tested this approach, yet (I'm discovering autoIt scripting language and the script below is the second one, I wrote).

Presented .bat files show the only approach I found in order to get in .bat file from .au3 script %ERRORCODE% and to test it.

The solution bases on WMI answers probably in a better way my needs – not to shut the computer when someone has an opened session. By the end of the week, I’ll try to test this approach. I haven't use the WMI with autoIt scripts, but looking at the exemples, I realize that the use of WMI is very very close to its use in vbs.

Best Regards

User3D

#cs ----------------------------------------------------------------------------

 AutoIt Version: 3.3.8.1
 Author:         Jacek
 Script version: 01a
 Use: "C:\Program Files (x86)\AutoIt3\AutoIt3.exe" CheckIdleTime.au3 [<File>]
                           If <File> is absent, the script works with ChkIdle.txt

 Script Function:
              This script is designated to be executed twice within another script.
              The script measures the time between its two launches and compares it to the computer idle time (neither keyboard nor mouse activity)
              The first script call creates the file with script launch date. If this file exists, the script considers that this is its second launch and compares the time between its two launches with computer idle time. Than it writes the result within the file.
              The positive value means that the idle computer time was bigger than the time between two script launches.
              The negative value means that there was a keyboard or a mouse event after the first launch of the script.
              The -99 value can also indicate an error (no distinction between an error and keyboard/mouse activity with this value.
              I use this script within .bat files to check if there was any user activity during the .bat execution.
              The example of such .bat file returning the comparison result (CheckIdleTime.bat) and of test script are below:
             
                           CheckIdleTime.bat
                           -----------------
                                         @echo OFF
                                         set ChkIdleTime=%1
                                         set ChkIdle=start /wait "C:\Program Files (x86)\AutoIt3\AutoIt3.exe" CheckIdletime.au3

                                         %ChkIdle% %ChkIdleTime%
                                         For /F "tokens=1,2* delims=: " %%i in (%ChkIdleTime%) DO if %%i==ReturnCode exit /B %%j
                                         rem if any issue with the command for a positive value is returned to make believe the calling process that there was
                                         rem some user activity
                                         exit /B -99

                          TestCheckIdleTime.bat
                           ---------------------
                                         @echo OFF
                                         set Scripts=C:\Donnees
                                         set ChkIdleTime=%TEMP%\ChkIldeTime_%RANDOM%.tmp
                                         rem All old semaphore files are deleted
                                         del /Q %TEMP%\ChkIldeTime_*.tmp
                                         cd %Scripts%
                                         call CheckIdleTime.bat %ChkIdleTime%
                                         echo 1st call return code: %ERRORLEVEL%

                                         rem just to make the script wait 10 seconds in order to test
                                         ping localhost -n 5 >nul

                                         rem TimeStamp fin processing
                                         call CheckIdleTime.bat %ChkIdleTime%
                                         If %ERRORLEVEL% LSS 0 (
                                                      echo 2nd call return code: %ERRORLEVEL% : keyboard or mouse activity detected
                                                      ) ELSE (
                                                      echo 2nd call return code: %ERRORLEVEL% : neither keyboard nor mouse activity during script execution
                                                      )
#ce ----------------------------------------------------------------------------

#include <Timers.au3>
#include <GUIConstantsEx.au3>
#include <Date.au3>
#include <WindowsConstants.au3>

Const $DefautName="ChkIdle.txt"        ; file name to be used if <File> parameter is absent
Const $OVERWRITE=2                                                      ; file open modes
Const $READ=0

Global $strtCur = _NowCalc()   ; script start date

; get filename (either fron the first parammeter - if exists - or take the defult one
If $CmdLine[0]>0 Then
   $name=$CmdLine[1]
Else
   $name=$DefautName
EndIf

Local $exitCode=0
Global $file = FileOpen($name, $READ) ; File result opening
; Check if file opened for reading OK
If $file = -1 Then
    $exitCode = StartPoint()
Else
    $exitCode = EndPoint()
EndIf
Exit($exitCode)

;------------------------------------ Functions
; Start point file creation
Func StartPoint()
              Local $exitCode = 0
              $file = FileOpen($name, $OVERWRITE) ; File result opening
              ; Check if file opened for writing OK
              If $file = -1 Then
                           $exitCode = -99
              Else
                           FileWriteLine($file, $strtCur & @CRLF)
                           FileWriteLine($file, "ReturnCode:" & $exitCode & @CRLF)
                           FileClose($file)
    EndIf
    Return $exitCode
EndFunc

;------------------------------------
; Inactivity time coparison
Func EndPoint()
              Local $strStartDate = FileReadLine($file)
              Local $diffDate = _DateDiff('s', $strStartDate, _NowCalc())
              Local $iIdleTime = _Timer_GetIdleTime()
              Local $iActivity= Floor(($iIdleTime / 1000) - $diffDate)
              FileClose($file)
              $file = FileOpen($name, $OVERWRITE)
              FileWriteLine($file, "ReturnCode:" & $iActivity & @CRLF)
              FileClose($file)
              Return $iActivity
EndFunc

Share this post


Link to post
Share on other sites
guinness

_WinAPI_GetIdleTime is in a UDF that can be found in the examples section called WinAPIEx. This is why you couldn't find it in the standard includes.


UDF List:

 
_AdapterConnections()_AlwaysRun()_AppMon()_AppMonEx()_ArrayFilter/_ArrayReduce_BinaryBin()_CheckMsgBox()_CmdLineRaw()_ContextMenu()_ConvertLHWebColor()/_ConvertSHWebColor()_DesktopDimensions()_DisplayPassword()_DotNet_Load()/_DotNet_Unload()_Fibonacci()_FileCompare()_FileCompareContents()_FileNameByHandle()_FilePrefix/SRE()_FindInFile()_GetBackgroundColor()/_SetBackgroundColor()_GetConrolID()_GetCtrlClass()_GetDirectoryFormat()_GetDriveMediaType()_GetFilename()/_GetFilenameExt()_GetHardwareID()_GetIP()_GetIP_Country()_GetOSLanguage()_GetSavedSource()_GetStringSize()_GetSystemPaths()_GetURLImage()_GIFImage()_GoogleWeather()_GUICtrlCreateGroup()_GUICtrlListBox_CreateArray()_GUICtrlListView_CreateArray()_GUICtrlListView_SaveCSV()_GUICtrlListView_SaveHTML()_GUICtrlListView_SaveTxt()_GUICtrlListView_SaveXML()_GUICtrlMenu_Recent()_GUICtrlMenu_SetItemImage()_GUICtrlTreeView_CreateArray()_GUIDisable()_GUIImageList_SetIconFromHandle()_GUIRegisterMsg()_GUISetIcon()_Icon_Clear()/_Icon_Set()_IdleTime()_InetGet()_InetGetGUI()_InetGetProgress()_IPDetails()_IsFileOlder()_IsGUID()_IsHex()_IsPalindrome()_IsRegKey()_IsStringRegExp()_IsSystemDrive()_IsUPX()_IsValidType()_IsWebColor()_Language()_Log()_MicrosoftInternetConnectivity()_MSDNDataType()_PathFull/GetRelative/Split()_PathSplitEx()_PrintFromArray()_ProgressSetMarquee()_ReDim()_RockPaperScissors()/_RockPaperScissorsLizardSpock()_ScrollingCredits_SelfDelete()_SelfRename()_SelfUpdate()_SendTo()_ShellAll()_ShellFile()_ShellFolder()_SingletonHWID()_SingletonPID()_Startup()_StringCompact()_StringIsValid()_StringRegExpMetaCharacters()_StringReplaceWholeWord()_StringStripChars()_Temperature()_TrialPeriod()_UKToUSDate()/_USToUKDate()_WinAPI_Create_CTL_CODE()_WinAPI_CreateGUID()_WMIDateStringToDate()/_DateToWMIDateString()Au3 script parsingAutoIt SearchAutoIt3 PortableAutoIt3WrapperToPragmaAutoItWinGetTitle()/AutoItWinSetTitle()CodingDirToHTML5FileInstallrFileReadLastChars()GeoIP databaseGUI - Only Close ButtonGUI ExamplesGUICtrlDeleteImage()GUICtrlGetBkColor()GUICtrlGetStyle()GUIEventsGUIGetBkColor()Int_Parse() & Int_TryParse()IsISBN()LockFile()Mapping CtrlIDsOOP in AutoItParseHeadersToSciTE()PasswordValidPasteBinPosts Per DayPreExpandProtect GlobalsQueue()Resource UpdateResourcesExSciTE JumpSettings INISHELLHOOKShunting-YardSignature CreatorStack()Stopwatch()StringAddLF()/StringStripLF()StringEOLToCRLF()VSCROLLWM_COPYDATAMore Examples...

Updated: 22/04/2018

Share this post


Link to post
Share on other sites
kylomas

User3D,

A complete solution is posted in #6. That script resets the countdown whenever there is input (KB or mouse normally). If the countdown expires it then check for other users. This is what I understood from your topic, is this not what you are looking for?

I realize that the use of WMI is very very close to its use in vbs.

WMI is WMI, the syntax of VBS is easily translated to AutoIT. An excellent resource for WMI AutoIT syntax is the AutoIT version of Scriptomatic. You can find it in the examples section.

kylomas

Edited by kylomas

Forum Rules         Procedure for posting code

"I like pigs.  Dogs look up to us.  Cats look down on us.  Pigs treat us as equals."

- Sir Winston Churchill

Share this post


Link to post
Share on other sites
User3D

Hello

 

Thank you for all your answers.

 

Finally, I realized that I asked the wrong question. My issue is related to Task Scheduler and the processing of the task launched during the night, when the PC hibernates. At the end of this task, I want to hibernate the PC again, unless someone has started some activity.

Even with the wrong question, yours answers helped me to find one possible solution. I created .au3 script, which reads System Events to detect the last wake up of PC from hibernate state, performs the requested night task (script parameter) and compares different times (from wake up, from last boot and inactivity time) in order to hibernate again or not the PC.

Thanks again for your answers, which helped me a lot in looking for a solution of my issue.

 

Best Regards

User3D

 

PS.

I’m more and more fond of AutoIt. Thanks for its creator(s)!

 

:ILA2:  

PS2.

I do not understand what is wrong with autoit code insertion!!! Sorry for the format but I was not able to quote this code correctly. I pasted it from Notepad++ :think: .

 

#cs ----------------------------------------------------------------------------

 AutoIt Version: 3.3.8.1
 Author:         Jacek
 Script version: 01a
 Use: "C:\Program Files (x86)\AutoIt3\AutoIt3.exe" NightScheduledTask.au3 <File .bat or .exe containing tasks to be executed>

 Script Function:
    This script is designed to be launched witin .bat file activated by Task Scheduler
    The steps of script work are as folow:
     - reading of System events in order to find the most recent date, when the PC was waked up from hibernate state
     - launch of the file defined as script parameter. (This file can empty the System events without disturbing NightScheduleTask operation.)
     - Hibernate PC, if the inactivity time exceeds the time from last hibernate wake up and the last system boot was done BEFOR teh system was hibernated
     
    The script appends its launch time, end time and errors in  C:\Temp\results_autoit.txt file
    The script was created with help of AutoIt Scriptomatic tool
    
#ce ----------------------------------------------------------------------------

; Output file name

$name="C:\Temp\results_autoit.txt"

#include <Timers.au3>
#include <Date.au3>

; file open modes
Const $APPEND=1
Const $OVERWRITE=2                  
Const $READ=0

; Shutdown constants
Const $LOGOFF=0
Const $SHUTDOWN=1
Const $REBOOT=2
Const $FORCE=4
Const $POWERDOWN=8
Const $FORCEIFHUNG=16
Const $STANDBY=32
Const $HIBERNATE=64
 
Const $wbemFlagReturnImmediately = 0x10
Const $wbemFlagForwardOnly = 0x20

$colItems = ""
$strComputer = "localhost"

Global $file = FileOpen($name, $APPEND) 
FileWriteLine($file,@CRLF & _Now() & " Script start: " & @ScriptName & @CRLF)

$objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\")
$wakeGMT=MostRecentWake() ; GMT time of most recent hibernate computer wake up

;Batch task execution
$ReturnCode = BatchTask()

; get last boot date and local time. Both are expressed as UTC local zone time
$requestClause = "SELECT * FROM Win32_OperatingSystem"
$colItems = $objWMIService.ExecQuery($requestClause, "WQL", _
                     $wbemFlagReturnImmediately + $wbemFlagForwardOnly)
If IsObj($colItems) then
    For $objItem In $colItems
        $currUTC=  WMIDateStringToDateYYYYMMDD($objItem.LocalDateTime)
        $BootUTC = WMIDateStringToDateYYYYMMDD($objItem.LastBootUpTime)
        $shift=StringRight($objItem.LastBootUpTime, 4)
    Next
    $wakeUTC= _DateAdd('n', $shift, WMIDateStringToDateYYYYMMDD($wakeGMT))
    $sinceWake= _DateDiff('s', $wakeUTC, $currUTC)
    $sinceBoot= _DateDiff('s', $BootUTC, $currUTC)
    $iIdleTime = _Timer_GetIdleTime()
    $iActivity= Floor($iIdleTime / 1000)
    If $wakeUTC > $BootUTC Then
        If $iActivity > $sinceWake Then
            FileWriteLine($file,_Now() & " Script end  : " & @ScriptName & " (system hibernate)" & @CRLF)
            FileClose($file)
            $i=Shutdown($HIBERNATE)
        Else
            FileWriteLine($file,_Now() & " Script end  : " & @ScriptName & @CRLF)
            FileClose($file)
        EndIf
    Else
        FileWriteLine($file,_Now() & " Script end  : " & @ScriptName & @CRLF)
        FileClose($file)
    EndIf
Else
    FileWriteLine($file,"No WMI Objects Found for class: " & "Win32_OperatingSystem" )
    FileClose($file)
Endif


;---------------------------------------------------------------------
; launch of Batch
Func BatchTask()

    Local $i=0
    If $CmdLine[0]>0 Then   
        Local $prog=$CmdLine[1]
        Local $param = " "
        for $i = 2 To $CmdLine[0] Step 1
            $param = $param & " "
        Next
        Local $pid=Run($prog & $param, "" )
        if $pid = 0 Then
            FileWriteLine($file, "Process Launch error: " & $prog & $param & @CRLF)
        Else
            $i=ProcessWaitClose($pid)
        EndIf
    Else
        FileWriteLine($file, "Program to launch not defined" & @CRLF)
    EndIf

EndFunc ; BatchTask()

;---------------------------------------------------------------------
; Each wake up of hibernate computer generates two events with EventCode 1 and Category 0 within System evet file
; The first one corresponds to the system wake up time and the second one corresponds to system time adjustement
; This function returns GMT in UTC string format of such most recent event found in System event file or 0 if not found 0
Func MostRecentWake()
    $requestClause = "SELECT * FROM Win32_NTLogEvent where Logfile = 'System' and Category = '0' and  EventCode = '1'"
    $colItems = $objWMIService.ExecQuery($requestClause, "WQL", _
                               $wbemFlagReturnImmediately + $wbemFlagForwardOnly)                 
    $wakeTime=0
    If IsObj($colItems) then
       For $objItem In $colItems
          if $objItem.TimeGenerated > $wakeTime Then
                    $wakeTime = $objItem.TimeGenerated
          EndIf
       Next
    Endif
    Return ($wakeTime)
EndFunc ; MostRecentWake()

;---------------------------------------------------------------------
; UTC date conversiuon to string YYYY/MM/DD HH:MM:SS
Func WMIDateStringToDateYYYYMMDD($dtmDate)
    Return (StringLeft($dtmDate, 4) & "/" & _
    StringMid($dtmDate, 5, 2) & "/" & StringMid($dtmDate, 7, 2) _
    & " " & StringMid($dtmDate, 9, 2) & ":" & StringMid($dtmDate, 11, 2) & ":" & StringMid($dtmDate,13, 2))
EndFunc ; WMIDateStringToDateYYYYMMDD($dtmDate)

After Jos, I edited the message following Kylomas advice.

Edited by User3D
updated the codebox... it nearly works correctly :)

Share this post


Link to post
Share on other sites
kylomas

User3D,

The forum has changed (for the better).  To add code try clicking the AutoIt code box then pasting your code into the box.  This seems to work for me.

Glad you found a solution!

kylomas


Forum Rules         Procedure for posting code

"I like pigs.  Dogs look up to us.  Cats look down on us.  Pigs treat us as equals."

- Sir Winston Churchill

Share this post


Link to post
Share on other sites
User3D

Hi

Edititing my post to follow Kylomas advice concerning autoit script insertion, I saw Line Number box. How does this line numbering works and what is its use? I put 10 expecting to have an "old fashion editor" line numbering used in some editors (10, 20, 30, .... etc.), but finally the code lines were numbered from 10 with a step of 1. Is it possible to define also a step for numbering in this box?

Bregs

User3D

Share this post


Link to post
Share on other sites
User3D

Hi,
Finally, the script I posted above doesn’t answer my needs. When I wrote it, I didn’t realize that inactivity time returned by Windows correspond to the current session and that there is no means to get overall computer inactivity time. I found in different forums, that there is a possibility using powercfg to get some system timers evolution, such as time to hibernate, but I was not able to put it in place.
Thus I adopted the following approach:
Issue:
In the evening, the computer is left in hibernate state. The Task Scheduler wakes it up during the night to perform some scheduled jobs. When the jobs are finished, the Task Scheduler leaves the computer in operation.
Objective:
To hibernate the computer at the end of scheduled tasks execution, but only and only if there is no active user.
Solution:
During quite a lot of time I looked how to check if someone started to work after the system wake up. I didn’t’ find neither function nor event answering this question, thus I adopted the following approach:

  • I added a new environment variable, which identifies a file
  • I created a scheduled task launched each time the user activates his session by giving a password, which updates the file identified by the variable
  • In the script, I test if the file was updated after the system wake-up. If so, it means that someone has connected, and I the script does not hibernate the computer

In addition, the script tests if another script instance is executing. If so, it ends without hibernating the computer.
 
I believe this approach addresses my issue. It seems to work correctly. I haven’t done any tests with PC on which the unique user hasn’t the password.
 
I compiled this script in console mode. The attached version is still with some displays, I put for debug purpose.
 
Thank you to all, who answered my post and in this manner helped me in looking for suitable for me solution for the issue, which, I believe, I didn’t presented clearly at the beginning.
 
Best Regards
 
User3D
 

#cs ----------------------------------------------------------------------------

 AutoIt Version: 3.3.8.1
 Author:         Jacek
 Script version: 01c
 Use: "C:\Program Files (x86)\AutoIt3\AutoIt3.exe" NightScheduledTask.au3 <File .bat or .exe containing tasks to be executed>

 Script Function:sleep 60
    This script is designed to be launched witin .bat file activated by Task Scheduler
    The steps of script work are as folow:
     - reading of System events in order to find the most recent date, when the PC was waked up from hibernate state
     - launch of the file defined as script parameter. (This file can empty the System events without disturbing NightScheduleTask operation.)
     - Check if other script occurences were launched. If so, exit the script
     - test the last session activation date by checking the update date of the file created onec session opened (specific task defined as scheduled one)
     - If the PC booted before wake any user session was opened since computer wake up --> hibernate the computer
     
    The script was created with help of AutoIt Scriptomatic tool
    
#ce ----------------------------------------------------------------------------


#include <Timers.au3>
#include <Date.au3>

; file open modes
Const $APPEND=1
Const $OVERWRITE=2                  
Const $READ=0

; Shutdown constants
Const $LOGOFF=0
Const $SHUTDOWN=1
Const $REBOOT=2
Const $FORCE=4
Const $POWERDOWN=8
Const $FORCEIFHUNG=16
Const $STANDBY=32
Const $HIBERNATE=64
 
Const $wbemFlagReturnImmediately = 0x10
Const $wbemFlagForwardOnly = 0x20

Const $SSTARTSESSION="STRATSESSION" ; environment variable with the name of the file wrtiten at the begining of each session
Const $WAITONCE=5 * 1000                ; pooling frequency in milseconds
Const $MAXWAIT= 2 * 60 * 60 * 60 * 1000 ; max waiting time for another task to finish
$colItems = ""
$strComputer = "localhost"

ConsoleWrite(_Now() & " " & @ScriptName & " : start  " & @CRLF)

$objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\")
$wakeGMT=MostRecentWake() ; GMT time of most recent hibernate computer wake up

;Batch task execution

$ReturnCode = BatchTask()

; get last boot date and local time. Both are expressed as UTC local zone time
$requestClause = "SELECT * FROM Win32_OperatingSystem"
$colItems = $objWMIService.ExecQuery($requestClause, "WQL", _
                     $wbemFlagReturnImmediately + $wbemFlagForwardOnly)
If IsObj($colItems) then
    For $objItem In $colItems
        $currUTC=  WMIDateStringToDateYYYYMMDD($objItem.LocalDateTime)
        $BootUTC = WMIDateStringToDateYYYYMMDD($objItem.LastBootUpTime)
        $shift=StringRight($objItem.LastBootUpTime, 4)
    Next
    $Output = "Restart after Stand-by (GMT) : " & WMIDateStringToDateYYYYMMDD($wakeGMT) & @CRLF
    ConsoleWrite($Output)
    $wakeUTC= _DateAdd('n', $shift, WMIDateStringToDateYYYYMMDD($wakeGMT))
    $Output = "Restart after Stand-by (UTC) : " & $wakeUTC & @CRLF
    ConsoleWrite($Output)
    $Output = "Last Boot Up Time      (UTC) : " & $BootUTC & @CRLF 
    ConsoleWrite($Output)
    $Output = "LocalDateTime          (UTC) : " &  $currUTC & @CRLF
    ConsoleWrite($Output)
    If $wakeUTC > $BootUTC Then
        ConsoleWrite("Computer was hibernated after the boot" & @CRLF)
    Else
        ConsoleWrite("Computer was NOT hibernated after the boot" & @CRLF)
    EndIf
    
    $sinceWake= _DateDiff('s', $wakeUTC, $currUTC)
    $sinceBoot= _DateDiff('s', $BootUTC, $currUTC)

    $Output=           "Since boot : " & $sinceBoot & "s" & @CRLF
    $Output= $Output & "Since wake : " & $sinceWake & "s" & @CRLF
    ConsoleWrite($Output)
    
    Local $list = ProcessList(@ScriptName)
    If $list[0][0] < 2 Then ; No other task with @ScriptName thus the script tests if the system is to hibernate
        Local $sessionFile=EnvGet("STARTSESSION") ; get the start session file name (writen by a script)
        Local $t = FileGetTime($sessionFile)
        Local $modif= $t[0] & "/" & $t[1] & "/" & $t[2] & " " & $t[3] & ":" & $t[4] & ":" & $t[5]
        Local $sinceSession=_DateDiff('s', $modif, $currUTC)
        ConsoleWrite($sessionFile & " modified " & $modif & " $sinceSession = " & $sinceSession & "s" & " @error=" & @error & @CRLF)
        If ($sinceBoot > $sinceWake) AND ($sinceSession > $sinceWake) Then
            ConsoleWrite(_Now() & " Computer is hibernated (since session open = " & $sinceSession & "s, since wake = " & $sinceWake & "s)" &  @CRLF)
            $i=Shutdown($HIBERNATE)
        Else
            ConsoleWrite(_Now() & " Computer is not shut (Since session open = " & $sinceSession & "s, since wake = " & $sinceWake & "s)" & @CRLF)
        EndIf
    Else
        ConsoleWrite(_Now() & " Computer is not shut - other tasks in progress"  & @CRLF)
    EndIf
Else
    ConsoleWrite(_Now() & " No WMI Objects Found for class: " & "Win32_OperatingSystem" )
Endif

Exit ; End of Script


;---------------------------------------------------------------------
; launch of Batch
Func BatchTask()

    Local $i=0
    If $CmdLine[0]>0 Then   
        Local $prog=$CmdLine[1]
        Local $param = " "
        for $i = 2 To $CmdLine[0] Step 1
            $param = $param & " "
        Next
        Local $pid=Run($prog & $param, "" )
        if $pid = 0 Then
            ConsoleWrite("Erreur lancement " & $prog & $param & @CRLF)
        Else
            ConsoleWrite( "Lancement " & $prog & $param & @CRLF & "pid=" & $pid & @CRLF)
            $i=ProcessWaitClose($pid)
            ConsoleWrite("End pid = " & $pid & " return = " & $i & " @error = " & @error & @CRLF)
        EndIf
    Else
        ConsoleWrite( "Program to launch not defined" & @CRLF)
    EndIf

EndFunc ; BarchTask()

;---------------------------------------------------------------------
; Each wake up of hibernate computer generates two events with EventCode 1 and Category 0 within System evet file
; The first one corresponds to the system wake up time and the second one corresponds to system time adjustement
; This function returns GMT in UTC string format of such most recent event found in System event file or 0 if not found 0
Func MostRecentWake()
    $requestClause = "SELECT * FROM Win32_NTLogEvent where Logfile = 'System' and Category = '0' and  EventCode = '1'"
    $colItems = $objWMIService.ExecQuery($requestClause, "WQL", _
                               $wbemFlagReturnImmediately + $wbemFlagForwardOnly)                 
    $wakeTime=0
    If IsObj($colItems) then
       For $objItem In $colItems
          if $objItem.TimeGenerated > $wakeTime Then
                    $wakeTime = $objItem.TimeGenerated
          EndIf
       Next
    Endif
    Return ($wakeTime)
EndFunc ; MostRecentWake()

;---------------------------------------------------------------------
; UTC date conversiuon to string YYYY/MM/DD HH:MM:SS
Func WMIDateStringToDateYYYYMMDD($dtmDate)
    Return (StringLeft($dtmDate, 4) & "/" & _
    StringMid($dtmDate, 5, 2) & "/" & StringMid($dtmDate, 7, 2) _
    & " " & StringMid($dtmDate, 9, 2) & ":" & StringMid($dtmDate, 11, 2) & ":" & StringMid($dtmDate,13, 2))
EndFunc ; WMIDateStringToDateYYYYMMDD($dtmDate)
Edited by User3D

Share this post


Link to post
Share on other sites
BrewManNH

Why don't you use the script ideas that kylomas and I posted that tells you if there's a user logged on to the computer instead of making some Rube Goldberg script to do it?


If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Share this post


Link to post
Share on other sites
kylomas

@BrewmanNH - Thanks 

Rube Goldberg

 

turned the afternoon around...


Forum Rules         Procedure for posting code

"I like pigs.  Dogs look up to us.  Cats look down on us.  Pigs treat us as equals."

- Sir Winston Churchill

Share this post


Link to post
Share on other sites
User3D

Hi,

The reason of Rube Goldberg approach is that the script is launched by Task Scheduler in background with administrator privileges and opens a session with my name. It executes the background tasks as system scan or backup which can last for some time. In the morning, if I'm logging as an active user before the script has finished, it does not considers my activity and shuts the computer. A possible work-around is to define a specific administrator account dedicated for Task Scheduler activated tasks. I haven't tested this approach and I do not know if it would work with some "frozen" different user sessions on PC.

The Kylomas and MVPs approach learnt me a lot, and thank for the examples, which learnt me a lot. However I had a lot of difficulties to transpose this example from interactive into batch approach, thus the reason of Rube Goldberg solution. I'll be grateful if you can help me simpler user-name independent approach, which works for background tasks. 

Brges

User3D

PS.

The script, I wrote, is my 3rd script written using AutoIt, which is genial from my point of view.

Edited by User3D

Share this post


Link to post
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
Sign in to follow this  

×