Jump to content

How do i control an uninstaller after its started?


Chimaera
 Share

Recommended Posts

Im using an uninstaller loop from an array of troublesome toolbars etc that i encounter regularly which works fine but

The uninstaller starts from this code

$Uninstall = RunWait($aUninstallList[$UninstallLoop] & ' /qb /quiet /passive /norestart')
Or
$Uninstall = RunWait($aUninstallList[$UninstallLoop] & ' /s /S /sp- /silent /norestart /remove /q0 /uninstall')

depending which type it is.

The problem is once the uninstaller fully starts the autoit loop runs on into the next pass and i end up with another installer started then another then the installers clash

Sometimes they have questions that have to be clicked to make them remove certain parts which i am not automating.

Is there a way to make them work one at a time?

I know the progress stuff in the example code below is weird ive not found a way to track the progress of the uninstaller yet so i did a rough give me some indication something is happening.

_WindowClose() just closes the popup windows from the uninstallers.

Here is the loop

For $UninstallLoop = 1 To $aUninstallList[0]
        GUICtrlSetData($hProgress, 0 & " %")
        Sleep(200)
        IniWrite(@ScriptDir & '\ErrorLog.ini', 'Programs Found', 'Total Number Is ', $sUninstallCount) ; Write Total Uninstallers Found
        GUICtrlSetData($hProgress, 20 & " %")
        Sleep(200)
        If StringInStr($aUninstallList[$UninstallLoop], 'MsiExec.exe', 1) Then ; Check For MSI Uninstaller
            GUICtrlSetData($hProgress, 40 & " %")
            Sleep(200)
            $Uninstall = RunWait($aUninstallList[$UninstallLoop] & ' /qb /quiet /passive /norestart') ; Uninstall MSI With Extra Switches
            Sleep(2000)
            If $Uninstall < 0 Then ; Error Box
                IniWrite(@ScriptDir & '\ErrorLog.ini', 'Error Code', 'Exit', ' $Uninstall = ' & $Uninstall) ; $aDisplayList[$NameLoop] & ' '
            ElseIf $Uninstall >= 1601 And $Uninstall <= 1614 Then
                IniWrite(@ScriptDir & '\ErrorLog.ini', 'Error Code', 'Exit', ' $Uninstall = ' & $Uninstall) ; $aDisplayList[$NameLoop] & ' '
            Else
                IniWrite(@ScriptDir & '\ErrorLog.ini', 'Error Code', 'Exit', 'No Errors Found') ; $aDisplayList[$NameLoop] & ' '
            EndIf
            GUICtrlSetData($hProgress, 60 & " %")
            If IsArray($aLocationList) Then
                _ArrayDisplay($aLocationList)
                For $installloop = 1 To $aLocationList[0]
                    DirRemove($aLocationList[$installloop], 1)
                Next
            EndIf
            GUICtrlSetData($hProgress, 90 & " %")
            Sleep(200)
            _WindowClose()
        Else
            GUICtrlSetData($hProgress, 30 & " %")
            Sleep(200)
            $Uninstall = RunWait($aUninstallList[$UninstallLoop] & ' /s /S /sp- /silent /norestart /remove /q0 /uninstall') ; Uninstall With Extra Switches
            Sleep(2000)
            GUICtrlSetData($hProgress, 50 & " %")
            Sleep(200)
            If $Uninstall < 0 Then ; Error Box
                IniWrite(@ScriptDir & '\ErrorLog.ini', 'Error Code', 'Exit', ' $Uninstall = ' & $Uninstall) ; $aDisplayList[$NameLoop] & ' '
            EndIf
            GUICtrlSetData($hProgress, 70 & " %")
            If IsArray($aLocationList) Then
                For $installloop = 1 To $aLocationList[0]
                    DirRemove($aLocationList[$installloop], 1)
                Next
            EndIf
        EndIf
        GUICtrlSetData($hProgress, 100 & " %")
        Sleep(200)
        _WindowClose()
    Next

Many thanks

Edited by Chimaera
Link to comment
Share on other sites

You can try and run each uninstaller on your PC and see what process is being used. I've had to do that many times. When you can do a

While ProcessExists("ProcessNameHere.exe")
Sleep(100)
Wend

I've even gone as far as doing a While WinActive loop because of MSIEXEC wanting to hang on me.

Maybe this might help.

Edited by Bearpocalypse
Link to comment
Share on other sites

A lot of the uninstallers work correctly but i think it is like jdelaney mentioned

The Run Wait starts but as the child starts it cuts loose as it thinks the process has ended and then it starts the next whilst the previous child is still running which triggers the error because 2 installers are running at the same time

Im trying to find a way or idea to hang onto the child and only loop after that child has finished so it cant run multiple ones.

Link to comment
Share on other sites

If it can help you,below is my _RunWaitChids() function that I used for a same unsintall problem. It works like RunWait, but also waits for child processes to be finish.

But for more flexibility, you can use _ProcessWaitCloseRec which does so same job than ProcessWaitClose(), but waits for child processesto bo finish..

#include <WinAPIProc.au3>

$PID = Run(@ComSpec & " /k start notepad & start calc")
_ProcessWaitCloseRec($PID)



; #FUNCTION# ====================================================================================================================
; Name ..........: _ProcessWaitCloseRec
; Description ...:  Pauses script execution until a given process and its childs processes not exist.
; Syntax ........: _ProcessWaitCloseRec($iPid)
; Parameters ....: $vProcess            - The name or PID of the process to check.
;                  $iTimeout            - [optional] Specifies how long to wait (in seconds). Default is to wait indefinitely.
; Return values .: Sucess       Returns 1
;                  Failure      0 if the wait timed out. Set @error to non-zero on error.
; Author ........: jguinch
; ===============================================================================================================================
Func _ProcessWaitCloseRec($vProcess,  $iTimeout = 0)
    Local $sProcesses = ProcessExists($vProcess), $aProcessList, $aChilds, $iContinue
    Local $hTimer = TimerInit()
    
    While 1
        If $iTimeout AND TimerDiff($hTimer) > $iTimeout * 1000 Then Return 0
        
        $iContinue = 0
        $aProcessList = StringRegExp($sProcesses, "\d+", 3)
        For $i = 0 To UBound($aProcessList) - 1
            If ProcessExists($aProcessList[$i]) Then $iContinue = 1

            $aChilds = _WinAPI_EnumChildProcess( $aProcessList[$i] )
            If NOT @error AND $aChilds[0][0] > 0 Then
                For $j = 1 To $aChilds[0][0]
                    If NOT StringRegExp($sProcesses, "(?:^|;)" & $aChilds[$j][0] & "(?:;|$)") Then
                        $sProcesses &= ";" & $aChilds[$j][0]
                        $iContinue = 1
                    EndIf
                Next
            EndIf
            Sleep(10)
        Next

        If NOT $iContinue Then ExitLoop
    Wend

    Return 1
EndFunc

And _RunWaitChids (almost the same thing) :

#include <WinAPIProc.au3>

_RunWaitChids(@ComSpec & " /k start notepad & start calc")

; #FUNCTION# ====================================================================================================================
; Name ..........: _RunWaitChids
; Description ...:  Runs an external program and pauses script execution until the program and its clilds process finish.
; Syntax ........: _RunWaitChids($sProgram[, $sWorkingDir = ""[, $iShowFlag = @SW_SHOW]])
; Parameters ....: $sProgram            - The full path of the program (EXE, BAT, COM, or PIF) to run (see remarks).
;                  $sWorkingDir         - [optional] The working directory.
;                                           Blank ("") uses the current working directory. This is not the path to the program.
;                  $iShowFlag           - [optional] The "show" flag of the executed program:
;                                           @SW_HIDE = Hidden window (or Default keyword)
;                                           @SW_MINIMIZE = Minimized window
;                                           @SW_MAXIMIZE = Maximized window
; Return values .: Sucess       Returns 1
;                  Failure      Returns 0 and set @error to non-zero
; Author ........: jguinch
; ===============================================================================================================================
Func _RunWaitChids($sProgram, $sWorkingDir = "", $iShowFlag = @SW_SHOW)
    Local $aProcessList, $aChilds, $iContinue

    If $sWorkingDir = "" Or $sWorkingDir = Default Then $sWorkingDir = @WorkingDir
    If NOT FileExists($sWorkingDir) OR NOT StringInStr(FileGetAttrib($sWorkingDir), "D") Then Return SetError(2, 0, 0)
    If $iShowFlag <> @SW_SHOW AND $iShowFlag <> @SW_MINIMIZE AND $iShowFlag <> @SW_MAXIMIZE AND $iShowFlag <> Default Then Return SetError(3, 0, 0)


    Local $iPid = Run($sProgram, $sWorkingDir, $iShowFlag)
    If @error Then Return SetError(@error, @extended, 0)

    Local $sProcesses = $iPid

    While 1
        $iContinue = 0
        $aProcessList = StringRegExp($sProcesses, "\d+", 3)
        For $i = 0 To UBound($aProcessList) - 1
            If ProcessExists($aProcessList[$i]) Then $iContinue = 1

            $aChilds = _WinAPI_EnumChildProcess( $aProcessList[$i] )
            If NOT @error AND $aChilds[0][0] > 0 Then
                For $j = 1 To $aChilds[0][0]
                    If NOT StringRegExp($sProcesses, "(?:^|;)" & $aChilds[$j][0] & "(?:;|$)") Then
                        $sProcesses &= ";" & $aChilds[$j][0]
                        $iContinue = 1
                    EndIf
                Next
            EndIf
            Sleep(10)
        Next

        If NOT $iContinue Then ExitLoop
    Wend

    Return 1
EndFunc
Edited by jguinch
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...