Jump to content

How to close a main script and restart it.


Recommended Posts

Dear friends,

I have a main script that calls an auto update function that I put together messily due to lack of experience.  From within the auto update function, I query the new version that is available and the version of the current main script.  To date, I have been satisfied with renaming the main script and copying over the new version.  The end-users are then forced to manually re-run the main script after the file copy process completes.  Tonight, I was wondering if I can add a function to allow the closing of the main script and then restart the new main script from within the same function.  Can this be done?  I have provide the code to the auto update script I put together for your review.  Please provide insights and guidance if you know what I must do to achieve the desire objective.  Thank you very much for your time.

Edited:  I resolved my issue with help from your advices.  I ended up grabbing the process ID of the running XYZ app and then closed the process after restarting the updated version.  Thank you for your help.

Func AutoUpdater()
    Local $GetWorkingDir = @WorkingDir
    Local $NewVersion_SrcDir = "\Server1\XYZ\Updates\XYZ_app.exe"
    Local $ProductionVersion = $GetWorkingDir & "\XYZ_app.exe"
    Local $LatestVersion = FileGetVersion($NewVersion_SrcDir, "FileVersion")
    Local $CurrentVersion = FileGetVersion($ProductionVersion, "FileVersion")

    Local $Time = @MON & @MDAY & @HOUR & @MIN & @SEC
    Local $iPID = WinGetProcess("XYZ")

    If $LatestVersion > $CurrentVersion Then
        $Update = MsgBox(36, "XYZ - Auto Updater", "You are running version: " & $CurrentVersion & @CRLF & _
                "A newer version is available: " & $LatestVersion & @CRLF & @CRLF & "Do you want to download the latest version?")
        If $Update = 6 Then
            GUIDelete($XYZAPP)
            MsgBox(0, "XYZ - Auto Updater", "Closing application to download a newer version!", 3)
            FileMove($GetWorkingDir & "\XYZ_app.exe", $GetWorkingDir & "\XYZ_OLD." & $Time, 1)
            FileCopy($NewVersion_SrcDir, $ProductionVersion, 1)
            If FileExists($GetWorkingDir & "\XYZ_app.exe") Then
                MsgBox(0, "XYZ - Auto Updater", "Update Completed! Restarting XYZ application.", 3)
                ShellExecute($GetWorkingDir & "\XYZ_app.exe")
                ProcessClose($iPID)
            EndIf
        Else
            Sleep(100)
        EndIf
    ElseIf $LatestVersion = $CurrentVersion Then
        Sleep(100)
    EndIf
EndFunc   ;==>AutoUpdater

 

Edited by LisHawj
Link to comment
Share on other sites

Could you Run() or ShellExecute() the path to new file?

Also Exit current script.

Hmm Exit'ing might be hard I forget if those Run functions wait for close.

There might be a flag to prevent that, but I'm not sure off hand.

Edited by Xandy
Link to comment
Share on other sites

Guinness hast already written such a function:

 

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

I had to do something like this.  I make a batch file inside the EXE, with the source EXE name and @ScriptDir, then launch the batch file (starts a new process). Exit EXE. Batch file re-launches the EXE.

:)

 

Skysnake

Why is the snake in the sky?

Link to comment
Share on other sites

That's exactly what _SelfUpdate does :)

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

I used the _selfupdate but found that some times it failed to do as it should, though I newer found out why.

So I created an Update.exe, that I called from my main script with /fileversion /exename /PIDID

Then the Update.exe checked if there was an update, and if so, it closes the mains script using the PID, rename the mainscript to .bak, downloads the update, saving it with the filename, checks if the downloaded it ok, deletes the .bak and runs the main file.

This of curse requires that one have 2 files in the script dir, the main file and the updater.

I have build my updater upon https://github.com/J2TeaM/autoit-updater can't find the autoit thread, though I have modified the updater to use curl (by ward) and also updated the php files so they uses post and not get, and some other small changes/error correction (when hit 2 dig in version the php failed to get the latest update)

 

Cheers
/Rex

Link to comment
Share on other sites

Thank you, everyone.  I resolved my issue and have updated my code with the working changes.  I ended up grabbing the process ID of the running XYZ app and then closed the process after restarting the updated version.  Thank you for your help.

Link to comment
Share on other sites

  • 2 weeks later...

I wrote a generic updater that would read an INI file with values placed by the calling EXE. Here is the function to include in the EXE:

; #FUNCTION# ====================================================================================================================
; Name ..........: __CheckForNewVersion
; Description ...: Checks for a newer version of the software. If a newer version exists, a notification dialog will show. This
;                  does NOT update the software; it only lets the user know there's a newer version
; Syntax ........: __CheckForNewVersion()
; Parameters ....: None
; Return values .: None
; ===============================================================================================================================
Func __CheckForNewVersion()
  Local $theMessage
  If IniRead($INIFile, "General", "Version", "NA") > $theVersion Then
    ; Newer version exists than what is currently running
    $theMessage = "There is a newer version of {Your Software} available. Please update now." & @CRLF & @CRLF & "Your version: " & $theVersion & @CRLF & "New version: " & IniRead($INIFile, "General", "Version", "NA") & @CRLF & @CRLF & "NOTE: The version you currently use may not work properly as both the program and the data support files may have changed!" & @CRLF & @CRLF & "Would you like to update now?" & @CRLF
    If _ExtMsgBox(32, "Yes|No", "Update?", $theMessage, 0, "", 0, False) = 1 Then
      ; Set up an INI file for the updater
      IniWrite(@MyDocumentsDir & "\Update.INI", "Update", "ScriptName", "{The EXE name}")
      IniWrite(@MyDocumentsDir & "\Update.INI", "Update", "ScriptFullPath", @ScriptFullPath)
      IniWrite(@MyDocumentsDir & "\Update.INI", "Update", "ScriptTitle", "{Your Software}")
      IniWrite(@MyDocumentsDir & "\Update.INI", "Update", "OldVersion", {The Current Version Number})
      IniWrite(@MyDocumentsDir & "\Update.INI", "Update", "UpdatePath", {Path to the newer EXE})
      IniWrite(@MyDocumentsDir & "\Update.INI", "Update", "NewVersion", {The Update Version Number})
      Run(@ScriptDir & "\Updater.exe")
      Exit
    Else
      _ExtMsgBox(64, "OK", "Update Information", "You will continue to be reminded to update until you actually do update.", 0, "", 0, False)
    EndIf
  EndIf
EndFunc   ;==>__CheckForNewVersion

Also in the EXE, you need to include the line to remove existing Updater INI file:

If FileExists(@MyDocumentsDir & "\Update.INI") Then
  FileDelete(@MyDocumentsDir & "\Update.INI")
EndIf

My Updater then uses the information in the INI to back up the older version and copy in the newer version:

; ===============================================================================================================================
;  Updater                                                       AutoIt Script
;
; This is an automatic updater. It is called within a script. It relies on a
; dynamically created INI file.
; ===============================================================================================================================
#NoTrayIcon

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
  #AutoIt3Wrapper_Icon="{Path to the icon}\updater.ico"
  #AutoIt3Wrapper_Compression=4
  #AutoIt3Wrapper_UseUpx=y
  #AutoIt3Wrapper_UseX64=N
  #AutoIt3Wrapper_Res_Description=Updates the script
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****

#include <GUIConstants.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#include <EditConstants.au3>
#include <StringSize.au3>
#include <ExtMsgBox.au3>

; ===============================================================================================================================
; Globals
$theVersion = "20170105"
$theFont = "Tahoma"
$theFontSize = 10
$theBkColor = "0xECE9D8"
$theSource = @TempDir & __RandomTempFolder()

_ExtMsgBoxSet(-1, -1, 0xFFFFFF, -1, $theFontSize, $theFont, 370, 480)

$theFormWidth = 520
$theFormHeight = 370
$theButtonHeight = 24
$theButtonWidth = 90
$theMargin = 10
$theLeftMargin = 2 * $theMargin
$theTextWidth = $theFormWidth - 2 * $theLeftMargin
$theTitleHeight = 30
$theMessageHeight = 100
$theProgressHeight = 20

$INIFile = @MyDocumentsDir & "\Updater.INI"

$theScriptName = IniRead($INIFile, "Update", "ScriptName", "NA")
$theScriptFullPath = IniRead($INIFile, "Update", "ScriptFullPath", "NA")
$theScriptTitle = IniRead($INIFile, "Update", "ScriptTitle", "NA")
$theOldVersion = IniRead($INIFile, "Update", "OldVersion", "NA")
$theUpdatePath = IniRead($INIFile, "Update", "UpdatePath", "NA")
$theNewVersion = IniRead($INIFile, "Update", "NewVersion", "NA")

__Initialize()

$frmMain = GUICreate("Updater", $theFormWidth, $theFormHeight)
GUISetBkColor($theBkColor, $frmMain)
GUISetFont($theFontSize, 400, 0, $theFont)
GUICtrlCreateGraphic(0, 60, $theFormWidth + 10, 2, $SS_ETCHEDHORZ)
GUICtrlCreateGraphic(0, 0, $theFormWidth, 60)
GUICtrlSetBkColor(-1, 0xFFFFFF)
GUICtrlCreateGraphic(0, $theFormHeight - ($theButtonHeight + 2 * $theMargin), $theFormWidth + 10, 2, $SS_ETCHEDHORZ)
;GUICtrlCreatePic($theSource & "\updater.jpg", 0, 0, $theImageWidth, $theFormHeight - ($theButtonHeight + 2 * $theMargin))
GUICtrlCreatePic($theSource & "\updater1.jpg", $theFormWidth - 54, 6, 48, 48)
$lblTitle = GUICtrlCreateLabel("", $theLeftMargin, 15, $theTextWidth - 60, $theTitleHeight)
GUICtrlSetFont(-1, $theFontSize * 1.6, 800, 2, $theFont)
GUICtrlSetBkColor(-1, 0xFFFFFF)
; version
GUICtrlCreateLabel("v" & $theVersion, 2, $theFormHeight - 15, 150, 15)
GUICtrlSetFont(-1, $theFontSize * 0.8, 400, 1, $theFont)
GUICtrlSetColor(-1, "0x808080")

$lblMessage = GUICtrlCreateLabel("", $theLeftMargin, 2 * $theTitleHeight + 2* $theMargin, $theTextWidth, $theMessageHeight)

$prgStatus = GUICtrlCreateProgress($theLeftMargin, $theTitleHeight + $theMessageHeight + 5 * $theMargin, $theTextWidth, $theProgressHeight)
GUICtrlSetState(-1, $GUI_HIDE)

GUICtrlCreateLabel("Old Version: " & $theOldVersion, $theLeftMargin, $theFormHeight - (3 * $theButtonHeight + 3 * $theMargin), $theTextWidth, $theButtonHeight)
GUICtrlCreateLabel("New Version: " & $theNewVersion, $theLeftMargin, $theFormHeight - (2 * $theButtonHeight + 3 * $theMargin), $theTextWidth, $theButtonHeight)

$btnCancel = GUICtrlCreateButton("Cancel", $theFormWidth - $theButtonWidth - $theMargin, $theFormHeight - $theButtonHeight - $theMargin, $theButtonWidth, $theButtonHeight)
$btnBegin = GUICtrlCreateButton("Update", $theFormWidth - 2 * ($theButtonWidth + $theMargin), $theFormHeight - $theButtonHeight - $theMargin, $theButtonWidth, $theButtonHeight)
$btnDone = GUICtrlCreateButton("Done", $theFormWidth - 2 * ($theButtonWidth + $theMargin), $theFormHeight - $theButtonHeight - $theMargin, $theButtonWidth, $theButtonHeight)
GUICtrlSetState(-1, $GUI_HIDE)

GUICtrlSetData($lblTitle, "Welcome")
GUICtrlSetData($lblMessage, "Welcome to the " & $theScriptTitle & " updater." & @CRLF & @CRLF & "Click the Next button to begin.")

GUISetState(@SW_SHOW, $frmMain)

While 1
  Switch GUIGetMsg()
    Case $GUI_EVENT_CLOSE, $btnCancel
      If _ExtMsgBox(32, "Yes|No", "Verify", "Are you sure you want to exit?", 0, $frmMain, 0, False) = 1 Then
        ExitLoop
      EndIf
    Case $btnBegin
      GUICtrlSetState($btnBegin, $GUI_DISABLE)
      GUICtrlSetState($btnCancel, $GUI_DISABLE)
      __UpdateNow()
      GUICtrlSetState($btnBegin, $GUI_HIDE)
      GUICtrlSetState($btnCancel, $GUI_HIDE)
      GUICtrlSetState($btnDone, $GUI_SHOW)
    Case $btnDone
      GUICtrlSetData($lblTitle, "Update Launch")
      GUICtrlSetData($lblMessage, "Launching " & $theScriptName & "...")
      Sleep(500)
      ExitLoop
  EndSwitch
WEnd

GUISetState(@SW_HIDE, $frmMain)
Run($theScriptFullPath)
DirRemove($theSource, 1)

Exit

; ===============================================================================================================================
;  Nothing beyond here except functions called above
; ===============================================================================================================================

; #FUNCTION# ====================================================================================================================
; Name ..........: __UpdateNow
; Description ...: The "work" of the program
; Syntax ........: __UpdateNow()
; Parameters ....: None
; Return values .: None
; ===============================================================================================================================
Func __UpdateNow()
  ; Local variables
  Local $theIncrement, $theFirstRegistryKey, $theSecondRegistryKey, $theUninstallRegistryKey
  GUICtrlSetData($prgStatus, 10)
  GUICtrlSetData($lblMessage, "Backing up version " & $theOldVersion & " of " & $theScriptTitle & "...")
  __BackupCurrentFile($theScriptFullPath, @ScriptDir)
  Sleep(500)
  GUICtrlSetData($prgStatus, 20)
  GUICtrlSetData($lblMessage, "Copying version " & $theNewVersion & " of " & $theScriptTitle & " to the proper location...")
  FileCopy($theUpdatePath & Chr(92) & $theScriptName, $theScriptFullPath, 1)
  Sleep(500)
  GUICtrlSetData($prgStatus, 70)
  GUICtrlSetData($lblMessage, "Updating registry information for " & $theScriptTitle & "...")
  ; First get the GUID of the program to change the version listed in "Programs
  ; and Features". Gotta search these two keys:
  $theFirstRegistryKey = "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall"
  $theSecondRegistryKey = "HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
  $theIncrement = 1
  $theUninstallRegistryKey = ""
  While 1
    $theKeyToCheck = RegEnumKey($theFirstRegistryKey, $theIncrement)
    If @error Then ExitLoop
    If StringInStr(RegRead($theFirstRegistryKey & Chr(92) & $theKeyToCheck, "DisplayName"), $theScriptTitle) > 1 Then
      $theUninstallRegistryKey = $theFirstRegistryKey & Chr(92) & $theKeyToCheck & Chr(92) & "DisplayVersion"
      ExitLoop
    EndIf
    $theIncrement = $theIncrement + 1
  WEnd
  If $theUninstallRegistryKey = "" Then
    While 1
      $theKeyToCheck = RegEnumKey($theSecondRegistryKey, $theIncrement)
      If @error Then ExitLoop
      If StringInStr(RegRead($theSecondRegistryKey & Chr(92) & $theKeyToCheck, "DisplayName"), $theScriptTitle) > 1 Then
        $theUninstallRegistryKey = $theSecondRegistryKey & Chr(92) & $theKeyToCheck & Chr(92) & "DisplayVersion"
        ExitLoop
      EndIf
      $theIncrement = $theIncrement + 1
    WEnd
  EndIf
  If $theUninstallRegistryKey = "" Then
    _ExtMsgBox(48, "OK", "Verify", "Could not locate the GUID for the program. The update will continue without updating the version number in the registry.", 0, $frmMain, 0, False)
  Else
    RegWrite($theUninstallRegistryKey, "DisplayVersion", "REG_SZ", $theNewVersion)
    Sleep(500)
  EndIf
  GUICtrlSetData($prgStatus, 90)
  GUICtrlSetData($lblTitle, "Complete")
  GUICtrlSetData($lblMessage, "The update of " & $theScriptTitle & " to version " & $theNewVersion & " has successfully completed.")
  Sleep(1000)
  GUICtrlSetState($btnDone, $GUI_SHOW)
EndFunc   ;==>__UpdateNow

; #FUNCTION# ====================================================================================================================
; Name ..........: __RandomTempFolder
; Description ...: Creates a random temp folder to use while this is running in order to store any files needed and included
;                  in the script run
; Syntax ........: __RandomTempFolder()
; Parameters ....: None
; Return values .: None
; ===============================================================================================================================
Func __RandomTempFolder()
  Local $i, $theFolder, $theCharacter
  $theFolder = "\~"
  For $i = 1 To 10
    $theCharacter = Random(97, 122, 1)
    $theFolder = $theFolder & Chr($theCharacter)
  Next
  Return $theFolder
EndFunc   ;==>__RandomTempFolder

; #FUNCTION# ====================================================================================================================
; Name ..........: __BackupCurrentFile
; Description ...: ; Backs up the given file, including the path to the file, with a numerical extension. The backups are kept
;                    in the same folder.
; Syntax ........: __BackupCurrentFile($theFile, $thePath)
; Parameters ....: $theFile             - the name of the file
;                  $thePath             - the path to the file
; Return values .: None
; ===============================================================================================================================
Func __BackupCurrentFile($theFile, $thePath)
  Local $theNumericalExtension
  $theNumericalExtension = 0
  While $theNumericalExtension < 999
    $theExtension = StringRight("000" & String($theNumericalExtension), 3)
    If Not FileExists($thePath & Chr(92) & $theFile & "." & $theExtension) Then
      ExitLoop
    EndIf
    $theNumericalExtension = $theNumericalExtension + 1
  WEnd
  FileCopy($thePath & Chr(92) & $theFile, $thePath & Chr(92) & $theFile & "." & $theExtension, 1)
EndFunc   ;==>__BackupCurrentFile

; #FUNCTION# ====================================================================================================================
; Name ..........: __Initialize
; Description ...: Initialize any graphics needed
; Syntax ........: __Initialize()
; Parameters ....: None
; Return values .: None
; ===============================================================================================================================
Func __Initialize()
  ; First check the temp folder existence
  If Not FileExists($theSource) Then
    DirCreate($theSource)
  EndIf
  FileInstall("C:\Users\HiltonB\Documents\ISN AutoIt Studio\MyScripts\Updater\img\updater1.jpg", $theSource & "\updater1.jpg", 1)
EndFunc   ;==>__Initialize

I'd like to offer my apologies for using variables to create the GUI interface instead of using numbers, but I have found that sometimes I need to include more information and sometimes less information on the wizard style windows and by making them variables and drawing the parts of the wizard interface based on those variables it's easier to change the overall size by simply adjusting the variable name instead of going through many lines of code to adjust buttons and divider lines up/down/left/right.

Who lied and told you life would EVER be fair?

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