Jump to content

ShutdownTool


Kaimberex
 Share

Recommended Posts

 

I was recently asked by our packaging administrator to create a script to be used with our SCCM packages to prompt the user to restart the computer.  This tool is used with an ini file to pass parameters to the tool. This is my first big project and constructive criticism is welcome. 

Requires Process Functions UDF

EDIT: Thanks to @Danny35d for suggestions on the Processes array, and improved logging and overall cleaner functions. 

 

Changes:

 

Added a For loop checking running processes and writing the logs.  The While loop will take care of the waiting for the process to close before continuing with the shutdown.  The issue of using ProcessWaitClose() instead of the While loop is let say you want the tool to wait for winword.exe and excel.exe to be close before shutdown.  Now like any other computer user they close winword.exe, but then before closing excel.exe they reopen winword.exe. The script  never detected the second instant of winword.exe and shutdown.  In the other hand While loop is always checking the processes are close no matter which order close first before doing the shutdown.

 

#NoTrayIcon
#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
    #AutoIt3Wrapper_Res_Description=ShutdownTool
    #AutoIt3Wrapper_Res_Fileversion=2.1.3.44
    #AutoIt3Wrapper_Res_Fileversion_AutoIncrement=p
    #AutoIt3Wrapper_Res_LegalCopyright=AGCS 2016
    ;#AutoIt3Wrapper_Res_SaveSource=y
    #AutoIt3Wrapper_Res_Language=1033
    #AutoIt3Wrapper_Res_requestedExecutionLevel=requireAdministrator
    #AutoIt3Wrapper_Run_Tidy=y
    ;#Tidy_Parameters=/gd /reel /ri //kv 0 /sf
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
#cs ----------------------------------------------------------------------------

    AutoIt Version: 3.3.14.1
    Author:         Eric Behrens
    IT - Deskside Services
    Allianz Global Corporate & Specialty AG
    redrocker1988@gmail.com


    Script Function:
    A tool used with SCCM to display a pop up message to users should a restart, or logoff be required to finish installing a software update.

#ce ----------------------------------------------------------------------------
#Region Includes
    #include <ButtonConstants.au3>
    #include <File.au3>
    #include <GUIConstantsEx.au3>
    #include <StaticConstants.au3>
    #include <WindowsConstants.au3>
    #include <ComboConstants.au3>
    #include <GUIConstants.au3>
    #include <_ProcessFunctions.au3>
    #include <Array.au3>
    #include <Misc.au3>
#EndRegion Includes
HotKeySet("^!+e", "_AdminClose") ;allows a technician to terminate the tool before the timer runs out. Hotkey is Ctrl+Alt+Shift+e
#Region PreExecution
    #Region Declare Global Variables
        Global $GUI_2, $time, $lblMinimizeTimer, $btnRestart, $ticksElapsed, $timeElapsed
    #EndRegion Declare Global Variables
    #Region get the owner of the Explorer.exe process so that logging will work for the logged in user when the program is executed as the SYSTEM account.
        Global $ProcessOwner = _ProcessOpen(ProcessExists("explorer.exe"), 0x20000)
        Global $LoggedInUser = _ProcessGetOwner($ProcessOwner)
    #EndRegion get the owner of the Explorer.exe process so that logging will work for the logged in user when the program is executed as the SYSTEM account.
    #Region Read config.ini file and set parameters for runtime.
        Global $sTimer = IniRead(@ScriptDir & "\config.ini", "DefaultTimer", "Time", "7200");This reads the .ini file for the desired initial reboot timer. The default will be 2 hours if no timer is set.
        Global $CustomMessage = IniRead(@ScriptDir & "\config.ini", "CustomMessage", "Message", "Custom Message Here");This reads the specified custom message to be displayed in the restart dialog.
        Global $LogFileLocation = IniRead(@ScriptDir & "\config.ini", "Logging", "LogDir", "C:\Windows\ShutdownTool.log");this sets the log dir for logging. The default is set to C:\Windows\ShutdownTool.log
        Global $ShutDownParmeters = IniRead(@ScriptDir & "\config.ini", "Options", "Action", "Shutdown");the parameters set in the config.ini file tell the function ShutdownComputer() what to do when time runs out or when the restart button is pressed.
        Global $Logo = IniRead(@ScriptDir & "\config.ini", "Appearance", "Logo", "logo.jpg");Sets the logo
        Global $PostponeButton = IniRead(@ScriptDir & "\config.ini", "Options", "PostponeButton", "Disable");Disables Postpone button when minimized notification is restored.
        Global $Processes = IniReadSection(@ScriptDir & '\config.ini', 'Processes')
        Global $Logging = IniRead(@ScriptDir & "\config.ini", "Logging", "Logging", "Disable");Enables or disables logging.
    #EndRegion Read config.ini file and set parameters for runtime.
    #Region Logging
        If FileExists($LogFileLocation) = 0 Then _FileCreate($LogFileLocation) ;If the log file does not exist create a new log in specified logfile directory. If the file exists log entries will be appended to existing log.
        _FileWriteLog($LogFileLocation, "ShutdownTool Executed")
        $fileVersion = FileGetVersion(@ScriptDir & "\ShutdownTool.exe") ;Get the version of the file to display in the log.
        _FileWriteLog($LogFileLocation, "Author: Eric Behrens - IT - Deskside Services Allianz Global Corporate & Specialty AG")
        _FileWriteLog($LogFileLocation, "ShutdownTool Version " & $fileVersion)
        _FileWriteLog($LogFileLocation, "Log file dir = " & $LogFileLocation & ".")
        _FileWriteLog($LogFileLocation, "Parameters = " & $ShutDownParmeters & ".")

        If IsArray($Processes) Then
            For $x = 1 To $Processes[0][0]
                If $Processes[$x][1] = "" Then ContinueLoop
                _FileWriteLog($LogFileLocation, "Looking for running process, " & $Processes[$x][0] & ".")
                If ProcessExists($Processes[$x][1]) Then _FileWriteLog($LogFileLocation, "Found running process " & $Processes[$x][1] & "; halting execution until " & $Processes[$x][0] & " closes.")
            Next

            ;wait for the specified processes to close.
            Local $IsProcessRunning = True
            While $IsProcessRunning
                $IsProcessRunning = False
                For $x = 1 To $Processes[0][0]
                    If $Processes[$x][1] = "" Then ContinueLoop
                    If ProcessExists($Processes[$x][1]) Then $IsProcessRunning = True
                Next
                Sleep(10)

            WEnd
            _FileWriteLog($LogFileLocation, "ShutdownTool Notification Displayed")
        EndIf
    #EndRegion Logging
#EndRegion PreExecution
#Region Main Popup GUI
    Global $GUI_1 = GUICreate("AGCSShutdownTool", 464, 283, -1, -1, BitOR($WS_SYSMENU, $WS_POPUP), BitOR($WS_EX_TOOLWINDOW, $WS_EX_TOPMOST, $WS_EX_WINDOWEDGE))
    GUISetBkColor(0x004c92)
    Global $Pic1 = GUICtrlCreatePic(@ScriptDir & "\" & $Logo, 8, 8, 105, 41)
    Global $Pic2 = GUICtrlCreatePic(@ScriptDir & "\" & $Logo, 349, 7, 105, 41)
    Global $btnMinimize = GUICtrlCreateButton("Minimize", 8, 241, 121, 25)
    Global $btnRestart = GUICtrlCreateButton("", 335, 241, 121, 25)

    ;Set the text of the button based off of the specified shutdown parameters
    GUICtrlSetData($btnRestart, $ShutDownParmeters)

    Global $btnPostpone = GUICtrlCreateButton("Postpone", 195, 242, 73, 25)
    Global $lblActionInProgress = GUICtrlCreateLabel("", 120, 8, 225, 33, $SS_CENTER)
    GUICtrlSetFont(-1, 16, 400, 0, "MS Sans Serif")
    GUICtrlSetColor(-1, 0xFFFFFF)
    GUICtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT)

    GUICtrlSetData($lblActionInProgress, $ShutDownParmeters & " in Progress")

    Global $Label1 = GUICtrlCreateLabel($CustomMessage, 24, 80, 420, 73, $SS_CENTER)
    GUICtrlSetColor(-1, 0xFFFFFF)
    GUICtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT)
    Global $lblTimer = GUICtrlCreateLabel("", 160, 184, 145, 21, BitOR($SS_CENTER, $ES_READONLY))
    GUICtrlSetColor(-1, 0xFFFFFF)
    GUICtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT)
    Global $TimeCombo = GUICtrlCreateCombo("", 160, 208, 145, 25, BitOR($CBS_DROPDOWN, $CBS_AUTOHSCROLL))
    GUICtrlSetData(-1, "10 minutes|20 minutes|30 minutes|1 hour|2 hours|6 hours", "2 hours")
    GUISetState(@SW_SHOW)

    Global $ticks = $sTimer ; 2 hours default, displayed in seconds
    Global $ticksElapsed = 0
    _Display()
    AdlibRegister("_Run", 1000)
    While 1
        If $ticks = 0 Then
            _FileWriteLog($LogFileLocation, "Time has expired and " & $ShutDownParmeters & " has been initiated by " & $LoggedInUser & ".")
            _ProcessCloseHandle($ProcessOwner)
            _FileWriteLog($LogFileLocation, "Time Elapsed since notification was displayed " & $timeElapsed)
            ShutdownComputer()
        EndIf
        $nMsg = GUIGetMsg()
        Switch $nMsg
            Case $btnMinimize
                _FileWriteLog($LogFileLocation, $LoggedInUser & " minimized " & $ShutDownParmeters & " notification.")
                GUISetState(@SW_HIDE, $GUI_1)
                GUI2()
            Case $btnRestart
                _FileWriteLog($LogFileLocation, $LoggedInUser & " initiated " & $ShutDownParmeters & ".")
                _ProcessCloseHandle($ProcessOwner)
                _FileWriteLog($LogFileLocation, "Time Elapsed since notification was displayed " & $timeElapsed)
                ShutdownComputer()
            Case $TimeCombo
                _Display()
            Case $btnPostpone
                _ReadCombo()
                _Run()
                AdlibRegister("_Run", 1000)
                ;Minimize to notification area
                GUISetState(@SW_HIDE, $GUI_1)
                GUI2()
        EndSwitch
    WEnd
#EndRegion Main Popup GUI
#Region Functions
    Func _AdminClose()
        ;This is an administrative close function to stop the tool from launching. This is a technician only hotkey and must not be published to end users.
        _FileWriteLog($LogFileLocation, "Time Elapsed since notification was displayed " & $timeElapsed)
        _FileWriteLog($LogFileLocation, $ShutDownParmeters & " terminated by AdminClose hotkey.")
        Exit
    EndFunc   ;==>_AdminClose
    Func _Display()
        Local $sec, $min, $hr, $time
        $sec = StringFormat("%02i", Mod($ticks, 60))
        $min = StringFormat("%02i", Mod($ticks / 60, 60))
        $hr = StringFormat("%02i", Mod($ticks / 3600, 60))
        $time = $hr & ":" & $min & ":" & $sec
        GUICtrlSetData($lblTimer, $time)
        GUICtrlSetData($lblMinimizeTimer, $time)
    EndFunc   ;==>_Display
    Func _ReadCombo()
        $sMsg = GUICtrlRead($TimeCombo)
        Switch $sMsg
            Case "20 minutes"
                $ticks = 1200 + ($sTimer - $ticksElapsed)
            Case "10 minutes"
                $ticks = 600 + ($sTimer - $ticksElapsed)
            Case "30 minutes"
                $ticks = 1800 + ($sTimer - $ticksElapsed)
            Case "1 hour"
                $ticks = 3600 + ($sTimer - $ticksElapsed)
            Case "2 hours"
                $ticks = 7200 + ($sTimer - $ticksElapsed)
            Case "6 hours"
                $ticks = 21600 + ($sTimer - $ticksElapsed)
        EndSwitch
        If $Logging = "Enabled" Then
            FileOpen($LogFileLocation, 9)
            _FileWriteLog($LogFileLocation, $ShutDownParmeters & " was postponed for " & $sMsg & " by " & $LoggedInUser & ".")
        EndIf
    EndFunc   ;==>_ReadCombo
    Func _Run()
        $ticks -= 1
        _Display()
        $ticksElapsed += 1
        _TimeElapsed()
    EndFunc   ;==>_Run
    Func _TimeElapsed()
        Local $sec, $min, $hr, $time
        $sec = StringFormat("%02i", Mod($ticksElapsed, 60))
        $min = StringFormat("%02i", Mod($ticksElapsed / 60, 60))
        $hr = StringFormat("%02i", Mod($ticksElapsed / 3600, 60))
        $timeElapsed = $hr & ":" & $min & ":" & $sec
    EndFunc   ;==>_TimeElapsed
    Func GUI2()

        $aTaskbar = WinGetPos("[CLASS:Shell_TrayWnd]", "")
        $GUI_2 = GUICreate("", 160, 54, @DesktopWidth, @DesktopHeight, BitOR($WS_SYSMENU, $WS_POPUP), $WS_EX_TOPMOST)
        GUISetBkColor(0x004c92)
        $Text = GUICtrlCreateLabel("", 8, 8, 138, 20, $SS_CENTER)
        GUICtrlSetColor(-1, 0xFFFFFF)
        GUICtrlSetFont(-1, 10, 400, 0, "MS Sans Serif")
        GUICtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT)

        GUICtrlSetData($Text, $ShutDownParmeters & " in Progress")

;~      Switch $ShutDownParmeters
;~          Case $ShutDownParmeters = "Reboot"
;~              GUICtrlSetData($Text, "Restart in Progress")
;~          Case $ShutDownParmeters = "Logoff"
;~              GUICtrlSetData($Text, "Logoff in Progress")
;~          Case $ShutDownParmeters = "Shutdown"
;~              GUICtrlSetData($Text, "Shutdown in Progress")
;~          Case $ShutDownParmeters = "ForceReboot"
;~              GUICtrlSetData($Text, "Restart in Progress")
;~      EndSwitch

        $lblMinimizeTimer = GUICtrlCreateLabel("", 8, 32, 138, 17, $SS_CENTER)
        GUICtrlSetColor(-1, 0xFFFFFF)
        GUICtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT)
        $aWin = WinGetPos($GUI_2)
        WinMove($GUI_2, "", @DesktopWidth - $aWin[2] - 4, @DesktopHeight - $aWin[3] - $aTaskbar[3] - 4)
        GUISetState(@SW_SHOW)

        While 1
            If $ticks = 0 Then

                _FileWriteLog($LogFileLocation, "Time has expired and " & $ShutDownParmeters & " has been initiated by " & $LoggedInUser & ".")
                _FileWriteLog($LogFileLocation, "Time Elapsed since notification was displayed " & $timeElapsed)
                ShutdownComputer()
            EndIf

            $nMsg = GUIGetMsg()
            Switch $nMsg
                Case $Text
                    GUISetState(@SW_HIDE, $GUI_2)
                    GUISetState(@SW_SHOW, $GUI_1)
                    _FileWriteLog($LogFileLocation, $LoggedInUser & " restored " & $ShutDownParmeters & " notification.")
                    Switch $PostponeButton
                        Case "Disable"
                            GUICtrlSetState($btnPostpone, $GUI_Disable)
                            GUICtrlSetState($TimeCombo, $GUI_Disable)
                            _FileWriteLog($LogFileLocation, "Additional postpones disabled.")
                        Case "Enable"
                    EndSwitch

                    ExitLoop

            EndSwitch
        WEnd

    EndFunc   ;==>GUI2
    Func ShutdownComputer()
        _ProcessCloseHandle($ProcessOwner)
;~  The shutdown code is a combination of the following values:
;~     $SD_LOGOFF (0) = Logoff
;~     $SD_SHUTDOWN (1) = Shutdown
;~     $SD_REBOOT (2) = Reboot
;~     $SD_FORCE (4) = Force
;~     $SD_POWERDOWN (8) = Power down
;~     $SD_FORCEHUNG (16) = Force if hung
;~     $SD_STANDBY (32) = Standby
;~     $SD_HIBERNATE (64) = Hibernate
        Switch $ShutDownParmeters
            Case $ShutDownParmeters = "Reboot"
                Shutdown(2)
            Case $ShutDownParmeters = "Logoff"
                Shutdown(0)
            Case $ShutDownParmeters = "Shutdown"
                Shutdown(1)
            Case $ShutDownParmeters = "ForceReboot"
                Shutdown(6)
        EndSwitch
    EndFunc   ;==>ShutdownComputer
#EndRegion Functions
You do not need to run parameters with ShutdownTool.exe. 
All Parameters are configured in config.ini.

Config.ini MUST be placed in the same folder as ShutdownTool.exe.

Admin Hotkey

Ctrl+Alt+Shift+e

There is an AdminKey hotkey to terminate the tool should a technician need to close the tool before the timer runs out. This is an administrative close function to stop the tool from executing the shutdown sequence. This is a technician only hotkey and must not be published to end users.

CONFIG.INI settings


[DefaultTimer] 
This will set the timer that displays when initially launching the tool. The default timer is set to two hours. The time is set using seconds. Two hours is equal to 7200 seconds. The user will be able to postpone the timer for 10 minutes, 20 minutes, 30 minutes, 1 hour, 2 hours, 4 hours, or 6 hours.  The postponed time will be added to the initial timer. 

[Custom Message]
This section displays a custom message that will be displayed on the popup. 
If the computer requires a logoff instead of a reboot you must specifiy that in the message. If it requires a reboot you must specify that in the message. 

[Appearance]
There are placeholders for two logos. One in the upper right hand corner and upper left hand corner. The logo files must be images in .bmp or .jpg format and cannot exceed 237x88 pixels. Place the image in the same directory as ShutdownTool.exe and config.ini

[Processes]
The tool will not launch if there are running processes that are defined in this section. There are placeholders for up to 10 processes. You must include the process name listed in task manager. For instance WINWORD.exe. Once the processes are closed the tool will pop up with the default timer. 

[Logging]
This section tells the tool where the log file location will be. This must be a full path and cannot contain any spaces. The default location is C:\Windows\ShutdownTool.log.
The log entries will append to the end of the log file with date and time timestamps.
If you wish to disable Logging then make sure Logging=Disabled. If Logging=Enabled then LogDir must be specified.  

[Options]
This section tells the tool what to do when the timer runs out, or when the User clicks the Restart, Shutdown, or Logoff button. 

Logoff - will log the user off immediately. 
Shutdown - Will shutdown the computer immediately. 
Reboot - will reboot the computer if there are no active applications.
ForceReboot - will force the reboot.

ForceReboot is recommended if a reboot is required as it will not hang and the reboot will be enforced when the timer runs out. 

PostponeButton - This will enable or disable the ability to postpone the timer further when the minimized notification is restored. Disallowing the user to postpone more than one time. Default vaule is disable.

 

Download: 

ShutdownTool.zip

Edited by Kaimberex
Improved Logging and searching for running processes
Link to comment
Share on other sites

You've forgotten something, examples script can not run!

Anyway, I usually use the command "shutdown" integrated with the operating system 
with similar functionality without installing any additional applications!

 

Missing: #include <_ProcessFunctions.au3>

Edited by Trong

Regards,
 

Link to comment
Share on other sites

2 minutes ago, Trong said:

You've forgotten something, examples script can not run!

Trong,

why don't you post the error message you get so Kaimberex can fix the problem or tell you what you did wrong :huh:

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2022-02-19 - Version 1.6.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download
Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki
PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki
Task Scheduler (NEW 2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki

Standard UDFs:
Excel - Example Scripts - Wiki
Word - Wiki

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Link to comment
Share on other sites

11 minutes ago, Trong said:

You've forgotten something, examples script can not run!

Anyway, I usually use the command "shutdown" integrated with the operating system 
with similar functionality without installing any additional applications!

 

Missing: #include <_ProcessFunctions.au3>

Sorry I didnt think to include this in this example because it was already in my UDF includes folder.  You can find the UDF used here: Process Functions

Link to comment
Share on other sites

14 minutes ago, water said:

Trong,

why don't you post the error message you get so Kaimberex can fix the problem or tell you what you did wrong :huh:

Thanks I started on this project last year and forgot that I included another UDF not included with Autoit base install. 

Link to comment
Share on other sites

Wonderful -_-

I choose the quickest solution for test not need download any UDF:

#NoTrayIcon
#include <File.au3>
#include <GUIConstants.au3>
#include <Security.au3>

HotKeySet("^!+e", "_AdminClose")
Global $GUI_2, $time, $lblMinimizeTimer, $btnRestart, $ticksElapsed, $timeElapsed
Global $ProcessOwner = _ProcessOpen(ProcessExists("explorer.exe"), 0x20000)
Global $LoggedInUser = _ProcessGetOwner($ProcessOwner)
Global $sTimer = IniRead(@ScriptDir & "\config.ini", "DefaultTimer", "Time", "7200")
Global $CustomMessage = IniRead(@ScriptDir & "\config.ini", "CustomMessage", "Message", "Custom Message Here")
Global $LogFileLocation = IniRead(@ScriptDir & "\config.ini", "Logging", "LogDir", "")
Global $ShutDownParmeters = IniRead(@ScriptDir & "\config.ini", "Options", "Action", "Shutdown")
Global $Logo = IniRead(@ScriptDir & "\config.ini", "Appearance", "Logo", "logo.jpg")
Global $PostponeButton = IniRead(@ScriptDir & "\config.ini", "Options", "PostponeButton", "Disable")
Global $Logging = IniRead(@ScriptDir & "\config.ini", "Logging", "Logging", "Disable")
Global $Process1 = IniRead(@ScriptDir & "\config.ini", "Processes", "1", "")
Global $Process2 = IniRead(@ScriptDir & "\config.ini", "Processes", "2", "")
Global $Process3 = IniRead(@ScriptDir & "\config.ini", "Processes", "3", "")
Global $Process4 = IniRead(@ScriptDir & "\config.ini", "Processes", "4", "")
Global $Process5 = IniRead(@ScriptDir & "\config.ini", "Processes", "5", "")
Global $Process6 = IniRead(@ScriptDir & "\config.ini", "Processes", "6", "")
Global $Process7 = IniRead(@ScriptDir & "\config.ini", "Processes", "7", "")
Global $Process8 = IniRead(@ScriptDir & "\config.ini", "Processes", "8", "")
Global $Process9 = IniRead(@ScriptDir & "\config.ini", "Processes", "9", "")
Global $Process10 = IniRead(@ScriptDir & "\config.ini", "Processes", "10", "")
If $Logging = "Disabled" Then $LogFileLocation = ""
If $Logging = "" Then $LogFileLocation = ""
If $Logging = "Enabled" Then
    If FileExists($LogFileLocation) = 0 Then _FileCreate($LogFileLocation)
    _FileWriteLog($LogFileLocation, "ShutdownTool Executed")
    $fileVersion = FileGetVersion(@ScriptDir & "\ShutdownTool.exe")
    _FileWriteLog($LogFileLocation, "Author: Eric Behrens - IT - Deskside Services Allianz Global Corporate & Specialty AG")
    _FileWriteLog($LogFileLocation, "ShutdownTool Version " & $fileVersion)
    _FileWriteLog($LogFileLocation, "Log file dir = " & $LogFileLocation & ".")
    _FileWriteLog($LogFileLocation, "Parameters = " & $ShutDownParmeters & ".")
    If $Process1 = "" Then
    Else
        _FileWriteLog($LogFileLocation, "Looking for running process, " & $Process1 & ".")
        If ProcessExists($Process1) Then _FileWriteLog($LogFileLocation, "Found running process " & $Process1 & "; halting execution until " & $Process1 & " closes.")
    EndIf
    If $Process2 = "" Then
    Else
        _FileWriteLog($LogFileLocation, "Looking for running process, " & $Process2 & ".")
        If ProcessExists($Process2) Then _FileWriteLog($LogFileLocation, "Found running process " & $Process2 & "; halting execution until " & $Process2 & " closes.")
    EndIf
    If $Process3 = "" Then
    Else
        _FileWriteLog($LogFileLocation, "Looking for running process, " & $Process3 & ".")
        If ProcessExists($Process3) Then _FileWriteLog($LogFileLocation, "Found running process " & $Process3 & "; halting execution until " & $Process3 & " closes.")
    EndIf
    If $Process4 = "" Then
    Else
        _FileWriteLog($LogFileLocation, "Looking for running process, " & $Process4 & ".")
        If ProcessExists($Process4) Then _FileWriteLog($LogFileLocation, "Found running process " & $Process4 & "; halting execution until " & $Process4 & " closes.")
    EndIf
    If $Process5 = "" Then
    Else
        _FileWriteLog($LogFileLocation, "Looking for running process, " & $Process5 & ".")
        If ProcessExists($Process5) Then _FileWriteLog($LogFileLocation, "Found running process " & $Process5 & "; halting execution until " & $Process5 & " closes.")
    EndIf
    If $Process6 = "" Then
    Else
        _FileWriteLog($LogFileLocation, "Looking for running process, " & $Process6 & ".")
        If ProcessExists($Process6) Then _FileWriteLog($LogFileLocation, "Found running process " & $Process6 & "; halting execution until " & $Process6 & " closes.")
    EndIf
    If $Process7 = "" Then
    Else
        _FileWriteLog($LogFileLocation, "Looking for running process, " & $Process7 & ".")
        If ProcessExists($Process7) Then _FileWriteLog($LogFileLocation, "Found running process " & $Process7 & "; halting execution until " & $Process7 & " closes.")
    EndIf
    If $Process8 = "" Then
    Else
        _FileWriteLog($LogFileLocation, "Looking for running process, " & $Process8 & ".")
        If ProcessExists($Process8) Then _FileWriteLog($LogFileLocation, "Found running process " & $Process8 & "; halting execution until " & $Process8 & " closes.")
    EndIf
    If $Process9 = "" Then
    Else
        _FileWriteLog($LogFileLocation, "Looking for running process, " & $Process9 & ".")
        If ProcessExists($Process9) Then _FileWriteLog($LogFileLocation, "Found running process " & $Process9 & "; halting execution until " & $Process9 & " closes.")
    EndIf
    If $Process10 = "" Then
    Else
        _FileWriteLog($LogFileLocation, "Looking for running process, " & $Process10 & ".")
        If ProcessExists($Process10) Then _FileWriteLog($LogFileLocation, "Found running process " & $Process10 & "; halting execution until " & $Process10 & " closes.")
    EndIf
EndIf
ProcessWaitClose($Process1)
ProcessWaitClose($Process2)
ProcessWaitClose($Process3)
ProcessWaitClose($Process4)
ProcessWaitClose($Process5)
ProcessWaitClose($Process6)
ProcessWaitClose($Process7)
ProcessWaitClose($Process8)
ProcessWaitClose($Process9)
ProcessWaitClose($Process10)
Global $GUI_1 = GUICreate("ShutdownTool", 464, 283, -1, -1, BitOR($WS_SYSMENU, $WS_POPUP), BitOR($WS_EX_TOOLWINDOW, $WS_EX_TOPMOST, $WS_EX_WINDOWEDGE))
GUISetBkColor(0x004c92)
Global $Pic1 = GUICtrlCreatePic(@ScriptDir & "\" & $Logo, 8, 8, 105, 41)
Global $Pic2 = GUICtrlCreatePic(@ScriptDir & "\" & $Logo, 349, 7, 105, 41)
Global $btnMinimize = GUICtrlCreateButton("Minimize", 8, 241, 121, 25)
Global $btnRestart = GUICtrlCreateButton("", 335, 241, 121, 25)
Switch $ShutDownParmeters
    Case $ShutDownParmeters = "Reboot"
        GUICtrlSetData($btnRestart, "Restart")
    Case $ShutDownParmeters = "Logoff"
        GUICtrlSetData($btnRestart, "Logoff")
    Case $ShutDownParmeters = "Shutdown"
        GUICtrlSetData($btnRestart, "Shutdown")
    Case $ShutDownParmeters = "ForceReboot"
        GUICtrlSetData($btnRestart, "Restart")
EndSwitch
Global $btnPostpone = GUICtrlCreateButton("Postpone", 195, 242, 73, 25)
Global $lblActionInProgress = GUICtrlCreateLabel("", 120, 8, 225, 33, $SS_CENTER)
GUICtrlSetFont(-1, 16, 400, 0, "MS Sans Serif")
GUICtrlSetColor(-1, 0xFFFFFF)
GUICtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT)
Switch $ShutDownParmeters
    Case $ShutDownParmeters = "Reboot"
        GUICtrlSetData($lblActionInProgress, "Restart in Progress")
    Case $ShutDownParmeters = "Logoff"
        GUICtrlSetData($lblActionInProgress, "Logoff in Progress")
    Case $ShutDownParmeters = "Shutdown"
        GUICtrlSetData($lblActionInProgress, "Shutdown in Progress")
    Case $ShutDownParmeters = "ForceReboot"
        GUICtrlSetData($lblActionInProgress, "Restart in Progress")
EndSwitch
Global $Label1 = GUICtrlCreateLabel($CustomMessage, 24, 80, 420, 73, $SS_CENTER)
GUICtrlSetColor(-1, 0xFFFFFF)
GUICtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT)
Global $lblTimer = GUICtrlCreateLabel("", 160, 184, 145, 21, BitOR($SS_CENTER, $ES_READONLY))
GUICtrlSetColor(-1, 0xFFFFFF)
GUICtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT)
Global $TimeCombo = GUICtrlCreateCombo("", 160, 208, 145, 25, BitOR($CBS_DROPDOWN, $CBS_AUTOHSCROLL))
GUICtrlSetData(-1, "10 minutes|20 minutes|30 minutes|1 hour|2 hours|6 hours", "2 hours")
GUISetState(@SW_SHOW)
Global $ticks = $sTimer
Global $ticksElapsed = 0
_Display()
AdlibRegister("_Run", 1000)
While 1
    If $ticks = 0 Then
        If $Logging = "Enabled" Then
            _FileWriteLog($LogFileLocation, "Time has expired and " & $ShutDownParmeters & " has been initiated by " & $LoggedInUser & ".")
            _ProcessCloseHandle($ProcessOwner)
            _FileWriteLog($LogFileLocation, "Time Elapsed since execution " & $timeElapsed)
        EndIf
        ShutdownComputer()
    EndIf
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $btnMinimize
            If $Logging = "Enabled" Then
                _FileWriteLog($LogFileLocation, $LoggedInUser & " minimized " & $ShutDownParmeters & " notification.")
            EndIf
            GUISetState(@SW_HIDE, $GUI_1)
            GUI2()
        Case $btnRestart
            If $Logging = "Enabled" Then
                _FileWriteLog($LogFileLocation, $LoggedInUser & " initiated " & $ShutDownParmeters & ".")
                _FileWriteLog($LogFileLocation, "Time Elapsed since execution " & $timeElapsed)
            EndIf
            _ProcessCloseHandle($ProcessOwner)
            ShutdownComputer()
        Case $TimeCombo
            _Display()
        Case $btnPostpone
            _ReadCombo()
            _Run()
            AdlibRegister("_Run", 1000)
            GUISetState(@SW_HIDE, $GUI_1)
            GUI2()
    EndSwitch
WEnd
Func _AdminClose()
    If $Logging = "Enabled" Then
        _FileWriteLog($LogFileLocation, "Time Elapsed since execution " & $timeElapsed)
        _FileWriteLog($LogFileLocation, $ShutDownParmeters & " terminated by AdminClose hotkey.")
    EndIf
    Exit
EndFunc   ;==>_AdminClose
Func _Display()
    Local $sec, $min, $hr, $time
    $sec = StringFormat("%02i", Mod($ticks, 60))
    $min = StringFormat("%02i", Mod($ticks / 60, 60))
    $hr = StringFormat("%02i", Mod($ticks / 3600, 60))
    $time = $hr & ":" & $min & ":" & $sec
    GUICtrlSetData($lblTimer, $time)
    GUICtrlSetData($lblMinimizeTimer, $time)
EndFunc   ;==>_Display
Func _ReadCombo()
    Switch GUICtrlRead($TimeCombo)
        Case "20 minutes"
            If $Logging = "Enabled" Then
                FileOpen($LogFileLocation, 9)
                _FileWriteLog($LogFileLocation, $ShutDownParmeters & " was postponed for 20 minutes by " & $LoggedInUser & ".")
            EndIf
            $ticks = 1200 + ($sTimer - $ticksElapsed)
        Case "10 minutes"
            If $Logging = "Enabled" Then
                FileOpen($LogFileLocation, 9)
                _FileWriteLog($LogFileLocation, $ShutDownParmeters & " was postponed for 10 minutes by " & $LoggedInUser & ".")
            EndIf
            $ticks = 600 + ($sTimer - $ticksElapsed)
        Case "30 minutes"
            If $Logging = "Enabled" Then
                FileOpen($LogFileLocation, 9)
                _FileWriteLog($LogFileLocation, $ShutDownParmeters & " was postponed for 30 minutes by " & $LoggedInUser & ".")
            EndIf
            $ticks = 1800 + ($sTimer - $ticksElapsed)
        Case "1 hour"
            If $Logging = "Enabled" Then
                FileOpen($LogFileLocation, 9)
                _FileWriteLog($LogFileLocation, $ShutDownParmeters & " postponed for 1 hour by " & $LoggedInUser & ".")
            EndIf
            $ticks = 3600 + ($sTimer - $ticksElapsed)
        Case "2 hours"
            If $Logging = "Enabled" Then
                FileOpen($LogFileLocation, 9)
                _FileWriteLog($LogFileLocation, $ShutDownParmeters & " was postponed for 2 hours by " & $LoggedInUser & ".")
            EndIf
            $ticks = 7200 + ($sTimer - $ticksElapsed)
        Case "6 hours"
            If $Logging = "Enabled" Then
                FileOpen($LogFileLocation, 9)
                _FileWriteLog($LogFileLocation, $ShutDownParmeters & " was postponed for 6 hours by " & $LoggedInUser & ".")
            EndIf
            $ticks = 21600 + ($sTimer - $ticksElapsed)
    EndSwitch
EndFunc   ;==>_ReadCombo
Func _Run()
    $ticks -= 1
    _Display()
    $ticksElapsed += 1
    _TimeElapsed()
EndFunc   ;==>_Run
Func _TimeElapsed()
    Local $sec, $min, $hr, $time
    $sec = StringFormat("%02i", Mod($ticksElapsed, 60))
    $min = StringFormat("%02i", Mod($ticksElapsed / 60, 60))
    $hr = StringFormat("%02i", Mod($ticksElapsed / 3600, 60))
    $timeElapsed = $hr & ":" & $min & ":" & $sec
EndFunc   ;==>_TimeElapsed
Func GUI2()
    $aTaskbar = WinGetPos("[CLASS:Shell_TrayWnd]", "")
    $GUI_2 = GUICreate("", 160, 54, @DesktopWidth, @DesktopHeight, BitOR($WS_SYSMENU, $WS_POPUP), $WS_EX_TOPMOST)
    GUISetBkColor(0x004c92)
    $Text = GUICtrlCreateLabel("Restart in Progress", 8, 8, 138, 20, $SS_CENTER)
    GUICtrlSetColor(-1, 0xFFFFFF)
    GUICtrlSetFont(-1, 10, 400, 0, "MS Sans Serif")
    GUICtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT)
    Switch $ShutDownParmeters
        Case $ShutDownParmeters = "Reboot"
            GUICtrlSetData($Text, "Restart in Progress")
        Case $ShutDownParmeters = "Logoff"
            GUICtrlSetData($Text, "Logoff in Progress")
        Case $ShutDownParmeters = "Shutdown"
            GUICtrlSetData($Text, "Shutdown in Progress")
        Case $ShutDownParmeters = "ForceReboot"
            GUICtrlSetData($Text, "Restart in Progress")
    EndSwitch
    $lblMinimizeTimer = GUICtrlCreateLabel("", 8, 32, 138, 17, $SS_CENTER)
    GUICtrlSetColor(-1, 0xFFFFFF)
    GUICtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT)
    $aWin = WinGetPos($GUI_2)
    WinMove($GUI_2, "", @DesktopWidth - $aWin[2] - 4, @DesktopHeight - $aWin[3] - $aTaskbar[3] - 4)
    GUISetState(@SW_SHOW)
    While 1
        If $ticks = 0 Then
            If $Logging = "Enabled" Then
                _FileWriteLog($LogFileLocation, "Time has expired and " & $ShutDownParmeters & " has been initiated by " & $LoggedInUser & ".")
                _FileWriteLog($LogFileLocation, "Time Elapsed since execution " & $timeElapsed)
            EndIf
            ShutdownComputer()
        EndIf
        $nMsg = GUIGetMsg()
        Switch $nMsg
            Case $Text, $lblMinimizeTimer
                GUISetState(@SW_HIDE, $GUI_2)
                GUISetState(@SW_SHOW, $GUI_1)
                Switch $PostponeButton
                    Case "Disable"
                        GUICtrlSetState($btnPostpone, $GUI_DISABLE)
                        GUICtrlSetState($TimeCombo, $GUI_DISABLE)
                    Case "Enable"
                EndSwitch
                ExitLoop
        EndSwitch
    WEnd
EndFunc   ;==>GUI2
Func ShutdownComputer()
    _ProcessCloseHandle($ProcessOwner)
    Switch $ShutDownParmeters
        Case $ShutDownParmeters = "Reboot"
            Shutdown(2)
        Case $ShutDownParmeters = "Logoff"
            Shutdown(0)
        Case $ShutDownParmeters = "Shutdown"
            Shutdown(1)
        Case $ShutDownParmeters = "ForceReboot"
            Shutdown(6)
    EndSwitch
EndFunc   ;==>ShutdownComputer

Func __PFCloseHandle(ByRef $hHandle)
    If Not IsPtr($hHandle) Or $hHandle = 0 Then Return SetError(1, 0, False)
    Local $aRet = DllCall("kernel32.dll", "bool", "CloseHandle", "handle", $hHandle)
    If @error Then Return SetError(2, @error, False)
    If Not $aRet[0] Then Return SetError(3, @error, False)
    $hHandle = 0
    Return True
EndFunc   ;==>__PFCloseHandle
Func __PFEnforcePID(ByRef $vPID)
    If IsInt($vPID) Then Return True
    $vPID = ProcessExists($vPID)
    If $vPID Then Return True
    Return SetError(1, 0, False)
EndFunc   ;==>__PFEnforcePID
Func _ProcessOpen($vProcessID, $iAccess, $bInheritHandle = False)
    Local $aRet
    If $vProcessID = -1 Then
        $aRet = DllCall("kernel32.dll", "handle", "GetCurrentProcess")
        If @error Then Return SetError(2, @error, 0)
        Return $aRet[0]
    ElseIf Not __PFEnforcePID($vProcessID) Then
        Return SetError(16, 0, 0)
    EndIf
    $aRet = DllCall("kernel32.dll", "handle", "OpenProcess", "dword", $iAccess, "bool", $bInheritHandle, "dword", $vProcessID)
    If @error Then Return SetError(2, @error, 0)
    If Not $aRet[0] Then Return SetError(3, @error, 0)
    Return SetExtended($vProcessID, $aRet[0])
EndFunc   ;==>_ProcessOpen
Func _ProcessCloseHandle(ByRef $hProcess)
    If Not __PFCloseHandle($hProcess) Then Return SetError(@error, @extended, False)
    Return True
EndFunc   ;==>_ProcessCloseHandle
Func _ProcessGetOwner($hProcess, $vADVAPI32DLL = "advapi32.dll")
    If Not IsPtr($hProcess) Or $vADVAPI32DLL < 0 Then Return SetError(1, 0, "")
    Local $aOwnerSecInfo, $aGroupSecInfo, $sOwner = ""
    Local $aRet = DllCall($vADVAPI32DLL, "dword", "GetSecurityInfo", "handle", $hProcess, "int", 6, "dword", 3, "ptr*", 0, "ptr*", 0, "ptr*", 0, "ptr*", 0, "ptr*", 0)
    If @error Then Return SetError(2, @error, "")
    If $aRet[0] Then Return SetError(3, $aRet[0], "")
    $aOwnerSecInfo = _Security__LookupAccountSid($aRet[4])
    If IsArray($aOwnerSecInfo) And $aOwnerSecInfo[1] <> "BUILTIN" Then
        $sOwner = $aOwnerSecInfo[0]
    Else
        $aGroupSecInfo = _Security__LookupAccountSid($aRet[5])
        If IsArray($aGroupSecInfo) Then $sOwner = $aGroupSecInfo[0]
        If $sOwner = "None" Then $sOwner = @UserName
    EndIf
    $aRet = DllCall("kernel32.dll", "handle", "LocalFree", "handle", $aRet[8])
    If @error Then
        SetError(-2, @error)
    ElseIf $aRet[0] Then
        SetError(-3, $aRet[0])
    EndIf
    Return $sOwner
EndFunc   ;==>_ProcessGetOwner

 

Edited by Trong

Regards,
 

Link to comment
Share on other sites

  • Moderators
1 hour ago, Trong said:

Wonderful -_-

I choose the quickest solution for test not need download any UDF:

Once again in your efforts to one-up the OP you're showing a penchant for bad coding practices.

"Profanity is the last vestige of the feeble mind. For the man who cannot express himself forcibly through intellect must do so through shock and awe" - Spencer W. Kimball

How to get your question answered on this forum!

Link to comment
Share on other sites

  • Moderators

The OP was asking for constructive criticism for what, in my opinion, is a pretty solid attempt. It would do well @Trong if you started engaging the brain before posting.

That said - @Kaimberex if you would like some suggestions for your script, I would suggest taking a look at the link below. As a long-time SCCM admin, this has been the goto reboot tool for a number of years. The post is older, but I have worked with the Coretech guys a lot, and their stuff is top notch. 

Not saying give up what you're doing (sometimes the answer to "why reinvent the wheel?" is "because I can" :) ) but it may give you some ideas.

http://blog.coretech.dk/kea/configuration-manager-shutdown-utility/

"Profanity is the last vestige of the feeble mind. For the man who cannot express himself forcibly through intellect must do so through shock and awe" - Spencer W. Kimball

How to get your question answered on this forum!

Link to comment
Share on other sites

31 minutes ago, JLogan3o13 said:

The OP was asking for constructive criticism for what, in my opinion, is a pretty solid attempt. It would do well @Trong if you started engaging the brain before posting.

That said - @Kaimberex if you would like some suggestions for your script, I would suggest taking a look at the link below. As a long-time SCCM admin, this has been the goto reboot tool for a number of years. The post is older, but I have worked with the Coretech guys a lot, and their stuff is top notch. 

Not saying give up what you're doing (sometimes the answer to "why reinvent the wheel?" is "because I can" :) ) but it may give you some ideas.

http://blog.coretech.dk/kea/configuration-manager-shutdown-utility/

Our IT department currently uses the Coretech shutdown tool but it was missing one small feature that they liked and that was the ability to log actions for some reason IT wants to log certain things and thats why I added the logging features. The code posted here allows for anyone to customize to their liking by modifying the ini file. So yes I am well aware of the coretech tool as we use that now. We are just needing some logging features and the coretech currently does not offer that feature. Thanks for the info though! 

Like I said this is my first actual script that is not only being used by me. (I use Autoit to make my life and work day more efficient and script things I frequently have to do.) Some higher ups learned of my passion and asked if I would be interested in developing something and I took on the task and this is the result. 

Link to comment
Share on other sites

Thanks to @Danny35d for suggestions on the Processes array, and improved logging and overall cleaner functions. 

 

Changes:

 

Added a For loop checking running processes and writing the logs.  The While loop will take care of the waiting for the process to close before continuing with the shutdown.  The issue of using ProcessWaitClose() instead of the While loop is let say you want the tool to wait for winword.exe and excel.exe to be close before shutdown.  Now like any other computer user they close winword.exe, but then before closing excel.exe they reopen winword.exe. The script  never detected the second instant of winword.exe and shutdown.  In the other hand While loop is always checking the processes are close no matter which order close first before doing the shutdown.

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