Kaimberex Posted June 7, 2016 Share Posted June 7, 2016 (edited) 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. expandcollapse popup#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 expandcollapse popupYou 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 June 9, 2016 by Kaimberex Improved Logging and searching for running processes Link to comment Share on other sites More sharing options...
Trong Posted June 7, 2016 Share Posted June 7, 2016 (edited) 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 June 7, 2016 by Trong Regards, Link to comment Share on other sites More sharing options...
water Posted June 7, 2016 Share Posted June 7, 2016 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 My UDFs and Tutorials: Spoiler UDFs:Active Directory (NEW 2022-02-19 - Version 1.6.1.0) - Download - General Help & Support - Example Scripts - WikiExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example ScriptsOutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - WikiOutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - DownloadOutlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - WikiPowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - WikiTask Scheduler (NEW 2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki Standard UDFs:Excel - Example Scripts - WikiWord - Wiki Tutorials:ADO - WikiWebDriver - Wiki Link to comment Share on other sites More sharing options...
Kaimberex Posted June 7, 2016 Author Share Posted June 7, 2016 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 More sharing options...
Kaimberex Posted June 7, 2016 Author Share Posted June 7, 2016 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 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 More sharing options...
Trong Posted June 7, 2016 Share Posted June 7, 2016 (edited) Wonderful I choose the quickest solution for test not need download any UDF: expandcollapse popup#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 June 7, 2016 by Trong Regards, Link to comment Share on other sites More sharing options...
Moderators JLogan3o13 Posted June 7, 2016 Moderators Share Posted June 7, 2016 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 More sharing options...
Trong Posted June 7, 2016 Share Posted June 7, 2016 Sorry for the mistake again , I had a huff ! Srcipt Fixed! Regards, Link to comment Share on other sites More sharing options...
Moderators JLogan3o13 Posted June 7, 2016 Moderators Share Posted June 7, 2016 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 More sharing options...
Kaimberex Posted June 7, 2016 Author Share Posted June 7, 2016 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 More sharing options...
Kaimberex Posted June 9, 2016 Author Share Posted June 9, 2016 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 More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now