Sign in to follow this  
Followers 0
supercat

If...Else Statements in Application Install

9 posts in this topic

Hi everyone,

I am currently working on automating an install and just have a quick question.

The install process can be different from machine to machine depending on the configuration of the machine.

The install process can have 1 extra window to interact with depending on this configuration, so I currently have 2 exe's built. I would really like just 1 exe file to push out across the network.

So I wanted to know is this scenario possible and how would I script it:-

If WinActive (THE EXTRA WINDOW) then ControlClick (THE REQUIRED BUTTON)
Else (CONTINUE WITH SCRIPT)

I have tried various ways using If WinExists and WinWaitActive but cannot get it to complete.

I hope this makes sense and someone can enlighten me!

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

Having two different windows open for the same function is a bit tricky. The reason why it's probably failing is because WinWait() is running before the window comes up, so it resolves to 'else'. Try a loop looking for either window and perform the action there:

While 1
    Sleep(100)
    If WinExists("THE EXTRA WINDOW") Then
        ControlClick(THE REQUIRED BUTTON)
        [... do whatever you need to do after the click ...]
    ElseIf WinExists("THE OTHER WINDOW") Then
        ExitLoop
    EndIf
WEnd

[... continue script ...]
Edited by mechaflash213

Spoiler

“Hello, ladies, look at your man, now back to me, now back at your man, now back to me. Sadly, he isn’t me, but if he stopped using ladies scented body wash and switched to Old Spice, he could smell like he’s me. Look down, back up, where are you? You’re on a boat with the man your man could smell like. What’s in your hand, back at me. I have it, it’s an oyster with two tickets to that thing you love. Look again, the tickets are now diamonds. Anything is possible when your man smells like Old Spice and not a lady. I’m on a horse.”

 

Share this post


Link to post
Share on other sites

#3 ·  Posted (edited)

Just throwing this out there...whatever the installer is, check to see if it has a command line for installation rather than automating the windows.

Edit: Nevermind, just saw your other thread!

Edited by MrMitchell

Share this post


Link to post
Share on other sites

Thanks guys,

I just got it!

Start of script here
If WinActive (THE EXTRA WINDOW) then ControlClick (THE REQUIRED BUTTON)
REST OF SCRIPT HERE
Else (NO EXTRA WINDOW) then
REST OF SCRIPT HERE
ENDIF

(REST OF SCRIPT HERE) is the same after navigating past the (THE EXTRA WINDOW)

All works well now.

A couple of things though, I have tested on XP, Win7, 2k3, 2k8 and it seems that one of the screens (where I specify destination folder) in Win7 has a different instance of the "Next" button than all other OS's. So I have a different script for Win7, not an issue really but just strange.

The way I navigate every window in the install process is by using:

WinWaitActive (WINDOW)

ControlClick (WINDOW)

I have found if a user clicks elsewhere and unactivates a window the script pauses. Understandable.

Would I be better using:

WinWait (Window)

WinActivate (Window)

ControlClick (Window)

Thanks

Share this post


Link to post
Share on other sites

#5 ·  Posted (edited)

What I would do, is use the below function, based on the run commands returned PID...it retrieves all the windows that are created for the process, then you just have to loop through until you find the active one. Then, if you have a switch case statement for the title/text in the window, you can easily automate it.

I use the same thing on all my companies applications, because they love adding warning messages for everything.

Func _ProcessGetWindow($p_PID, $p_ReturnBestGuess = False)
; #FUNCTION# ============================================================================================================================
; Name...........: _ProcessGetWindow
;
; Description ...: Returns an array of HWNDs containing all windows owned by the process $p_PID, or optionally a single "best guess."
;
; Syntax.........: _ProcessGetWindow( $p_PID [, $p_ReturnBestGuess = False ])
;
; Parameters ....: $p_PID - The PID of the process you want the Window for.
;                $p_ReturnBestGuess - If True, function will return only 1 reult on a best-guess basis.
;                                        The "Best Guess" is the VISIBLE window owned by $p_PID with the longest title.
;
; Return values .: Success   - Return $_array containing HWND info.
;                                    $_array[0] = Number of results
;                                    $_array[n] = HWND of Window n
;
;                Failure     - Returns 0
;
;                Error   - Returns -1 and sets @error
;                                        1 - Requires a non-zero number.
;                                        2 - Process does not exist
;                                        3 - WinList() Error
;
; Author ........: Andrew Bobulsky, contact: RulerOf <at that public email service provided by Google>.
; Remarks .......: The reverse of WinGetProcess()
; =======================================================================================================================================
Local $p_ReturnVal[1] = [0]
Local $p_WinList = WinList()
If @error Then ;Some Error handling
SetError(3)
Return -1
EndIf
If $p_PID = 0 Then ;Some Error handling
SetError(1)
Return -1
EndIf
If ProcessExists($p_PID) = 0 Then ;Some Error handling
ConsoleWrite("_ProcessGetWindow: Process " & $p_PID & " doesn't exist!" & @CRLF)
SetError(2)
Return -1
EndIf
For $i = 1 To $p_WinList[0][0] Step 1
Local $w_PID = WinGetProcess($p_WinList[$i][1])
; ConsoleWrite("Processing Window: " & Chr(34) & $p_WinList[$i][0] & Chr(34) & @CRLF & " with HWND: " & $p_WinList[$i][1] & @CRLF & " and PID: " & $w_PID & @CRLF)
If $w_PID = $p_PID Then
;ConsoleWrite("Match: HWND " & $p_WinList[$i][1] & @CRLF)
$p_ReturnVal[0] += 1
_ArrayAdd($p_ReturnVal, $p_WinList[$i][1])
EndIf
Next
If $p_ReturnVal[0] > 1 Then
If $p_ReturnBestGuess Then
Do
    Local $i_State = WinGetState($p_ReturnVal[2])
    Local $i_StateLongest = WinGetState($p_ReturnVal[1])
    Select
     Case BitAND($i_State, 2) And BitAND($i_StateLongest, 2) ;If they're both visible
     If StringLen(WinGetTitle($p_ReturnVal[2])) > StringLen(WinGetTitle($p_ReturnVal[1])) Then ;And the new one has a longer title
     _ArrayDelete($p_ReturnVal, 1) ;Delete the "loser"
     $p_ReturnVal[0] -= 1 ;Decrement counter
     Else
     _ArrayDelete($p_ReturnVal, 2) ;Delete the failed challenger
     $p_ReturnVal[0] -= 1
     EndIf
     Case BitAND($i_State, 2) And Not BitAND($i_StateLongest, 2) ;If the new one's visible and the old one isn't
     _ArrayDelete($p_ReturnVal, 1) ;Delete the old one
     $p_ReturnVal[0] -= 1 ;Decrement counter
     Case Else ;Neither window is visible, let's just keep the first one.
     _ArrayDelete($p_ReturnVal, 2)
     $p_ReturnVal[0] -= 1
    EndSelect
Until $p_ReturnVal[0] = 1
EndIf
Return $p_ReturnVal
ElseIf $p_ReturnVal[0] = 1 Then
Return $p_ReturnVal ;Only 1 window.
Else
Return 0 ;Window not found.
EndIf
EndFunc ;==>_ProcessGetWindow
Edited by jdelaney

IEbyXPATH-Grab IE DOM objects by XPATH IEscriptRecord-Makings of an IE script recorder ExcelFromXML-Create Excel docs without excel installed GetAllWindowControls-Output all control data on a given window.

Share this post


Link to post
Share on other sites

#6 ·  Posted (edited)

If you want a completely blind installer, just update the button text array, and it will do it's thing untill the process finishes:

Dim $aButtonClickOrder[8] = ["Continue", "&Continue", "OK", "&OK", "Yes", "&Yes", "Install", "&Install"]
Dim $aExpectedWindowState[3] = [1, 2, 4] ; Window exists, visible, and enabled
$PID = Run()
While ProcessExists($PID)
 $bButtonClicked = False
 $aHWnds = _ProcessGetWindow ( $PID )
 If IsArray ( $aHWnds ) Then
  For $i = 0 To UBound ( $aHWnds ) - 1
   If WaitForWindowState ( $aHWnds[$i], $aExpectedWindowState, 0, 0 ) Then
    ; window exists, is visible, and is enabled.
    For $j = To UBound ( $aButtonClickOrder ) - 1
     $hButton = ControlGetHandle ( $aHWnds[$i], "", "[CLASS:Button; TEXT:" & $aButtonClickOrder[$j] & "]"
     If IsHWnd ( $hButton ) Then
      ; button exists
      If ControlCommand ( $aHWnds[$i], "", $hButton, "IsEnabled", "" ) Then
       ControlFocus ( $aHWnds[$i], "", $hButton )
       ControlClick (  $aHWnds[$i], "", $hButton )
       Sleep (2000)
       $bButtonClicked = True
       ExitLoop
      EndIf
     EndIf
    Next
    If $bButtonClicked Then ExitLoop
   EndIf
  Next
 EndIf
 Sleep ( 1000 )
WEnd
Func _ProcessGetWindow($p_PID, $p_ReturnBestGuess = False)
 ; #FUNCTION# ============================================================================================================================
 ; Name...........: _ProcessGetWindow
 ;
 ; Description ...: Returns an array of HWNDs containing all windows owned by the process $p_PID, or optionally a single "best guess."
 ;
 ; Syntax.........: _ProcessGetWindow( $p_PID [, $p_ReturnBestGuess = False ])
 ;
 ; Parameters ....: $p_PID - The PID of the process you want the Window for.
 ;              $p_ReturnBestGuess - If True, function will return only 1 reult on a best-guess basis.
 ;                                      The "Best Guess" is the VISIBLE window owned by $p_PID with the longest title.
 ;
 ; Return values .: Success   - Return $_array containing HWND info.
 ;                                  $_array[0] = Number of results
 ;                                  $_array[n] = HWND of Window n
 ;
 ;              Failure  - Returns 0
 ;
 ;              Error   - Returns -1 and sets @error
 ;                                      1 - Requires a non-zero number.
 ;                                      2 - Process does not exist
 ;                                      3 - WinList() Error
 ;
 ; Author ........: Andrew Bobulsky, contact: RulerOf <at that public email service provided by Google>.
 ; Remarks .......: The reverse of WinGetProcess()
 ; =======================================================================================================================================
 Local $p_ReturnVal[1] = [0]
 Local $p_WinList = WinList()
 If @error Then ;Some Error handling
  SetError(3)
  Return -1
 EndIf
 If $p_PID = 0 Then ;Some Error handling
  SetError(1)
  Return -1
 EndIf
 If ProcessExists($p_PID) = 0 Then ;Some Error handling
  ConsoleWrite("_ProcessGetWindow: Process " & $p_PID & " doesn't exist!" & @CRLF)
  SetError(2)
  Return -1
 EndIf
 For $i = 1 To $p_WinList[0][0] Step 1
  Local $w_PID = WinGetProcess($p_WinList[$i][1])
  ; ConsoleWrite("Processing Window: " & Chr(34) & $p_WinList[$i][0] & Chr(34) & @CRLF & " with HWND: " & $p_WinList[$i][1] & @CRLF & " and PID: " & $w_PID & @CRLF)
  If $w_PID = $p_PID Then
   ;ConsoleWrite("Match: HWND " & $p_WinList[$i][1] & @CRLF)
   $p_ReturnVal[0] += 1
   _ArrayAdd($p_ReturnVal, $p_WinList[$i][1])
  EndIf
 Next
 If $p_ReturnVal[0] > 1 Then
  If $p_ReturnBestGuess Then
   Do
    Local $i_State = WinGetState($p_ReturnVal[2])
    Local $i_StateLongest = WinGetState($p_ReturnVal[1])
    Select
     Case BitAND($i_State, 2) And BitAND($i_StateLongest, 2) ;If they're both visible
      If StringLen(WinGetTitle($p_ReturnVal[2])) > StringLen(WinGetTitle($p_ReturnVal[1])) Then ;And the new one has a longer title
       _ArrayDelete($p_ReturnVal, 1) ;Delete the "loser"
       $p_ReturnVal[0] -= 1 ;Decrement counter
      Else
       _ArrayDelete($p_ReturnVal, 2) ;Delete the failed challenger
       $p_ReturnVal[0] -= 1
      EndIf
     Case BitAND($i_State, 2) And Not BitAND($i_StateLongest, 2) ;If the new one's visible and the old one isn't
      _ArrayDelete($p_ReturnVal, 1) ;Delete the old one
      $p_ReturnVal[0] -= 1 ;Decrement counter
     Case Else ;Neither window is visible, let's just keep the first one.
      _ArrayDelete($p_ReturnVal, 2)
      $p_ReturnVal[0] -= 1
    EndSelect
   Until $p_ReturnVal[0] = 1
  EndIf
  Return $p_ReturnVal
 ElseIf $p_ReturnVal[0] = 1 Then
  Return $p_ReturnVal ;Only 1 window.
 Else
  Return 0 ;Window not found.
 EndIf
EndFunc   ;==>_ProcessGetWindow
Func WaitForWindowState($hwndCallersWindow, $aCallersExpectedWindowState, $sCallersTotalWaitSeconds, $sCallersWaitChecks)
 $iTotalWaitMilSec = $sCallersTotalWaitSeconds * 1000
 $iSleepMilSec = $iTotalWaitMilSec / $sCallersWaitChecks
 ; Get states to log
 $sExpectedStates = ""
 For $i = 0 To UBound($aCallersExpectedWindowState) - 1
  Switch $aCallersExpectedWindowState[$i]
   Case 1
    $sExpectedStates = $sExpectedStates & "Exists "
   Case 2
    $sExpectedStates = $sExpectedStates & "Visible "
   Case 4
    $sExpectedStates = $sExpectedStates & "Enabled "
   Case 8
    $sExpectedStates = $sExpectedStates & "Active "
   Case 16
    $sExpectedStates = $sExpectedStates & "Minimized "
   Case 32
    $sExpectedStates = $sExpectedStates & "Maximized "
   Case Else
    ;If $lgbPerformLog Then Call("SetLogAndActOnState", 0, 2, "WaitForWindowState()", "Callers Win State=[" & $aCallersExpectedWindowState[$i] & "], but values must be in (1,2,4,8,16,32).", False, False)
    Return False
  EndSwitch
 Next
 $sExpectedStates = StringStripWS($sExpectedStates, 7) ; Strip double spaces, trailing, and leading
 For $i = 0 To $sCallersWaitChecks
  $iWinState = WinGetState($hwndCallersWindow)
  $bExpectedState = True
  For $iCurrentCheck = 0 To UBound($aCallersExpectedWindowState) - 1
   If Not BitAND($iWinState, $aCallersExpectedWindowState[$iCurrentCheck]) Then
    $bExpectedState = False
    ExitLoop
   EndIf
  Next
  If $bExpectedState Then
   ; Log State is as expected
   ;If $lgbPerformLog Then Call("SetLogAndActOnState", 2, 2, "WaitForWindowState()", "Window State=[" & $iWinState & "] matches callers expected window state[s]=[" & $sExpectedStates & "].", False, False)
   Return True
  EndIf
  Sleep($iSleepMilSec)
 Next
 ; Log State did not match expected
 ;Call("SetLogAndActOnState", 0, 2, "WaitForWindowState()", "Window State=[" & $iWinState & "] did NOT match callers expected window state[s]=[" & $sExpectedStates & "] within expected seconds=[" & $sCallersTotalWaitSeconds & "]", False, False)
 Return False
EndFunc   ;==>WaitForWindowState




#include <Array.au3>
#include <GuiToolbar.au3>

$array = ProcessList("UnivMgr.exe")
_ArrayDisplay($array)
;~ $array = _ProcessGetWin ( $array[1][1] )

Exit



;~ #include <Array.au3>

;~ $test = "this is a string"
;~ $array = StringToASCIIArray ( $test )
;~ _ArrayDisplay ( $array )

;~ For $i = 0 To UBound ( $array ) - 1
;~  If $array[$i]
;~ Exit






Dim $array[1]
$iCounter = 1
While 1
 If Not WinExists("[CLASS:IEFrame; INSTANCE:" & $iCounter & "]") Then ExitLoop
 ReDim $array[$iCounter]
 $array[$iCounter - 1] = WinGetTitle("[CLASS:IEFrame; INSTANCE:" & $iCounter & "]")
 $iCounter += 1
WEnd
_ArrayDisplay($array)
Exit


Switch $SomeValuea & $SomeValueb
 Case False & False
  MsgBox(1, 1, "00")
 Case True & False
  MsgBox(1, 1, "10")
 Case False & True
  MsgBox(1, 1, "01")
 Case True & True
  MsgBox(1, 1, "11")
EndSwitch
Edited by jdelaney

IEbyXPATH-Grab IE DOM objects by XPATH IEscriptRecord-Makings of an IE script recorder ExcelFromXML-Create Excel docs without excel installed GetAllWindowControls-Output all control data on a given window.

Share this post


Link to post
Share on other sites

I just got it!

I know you're feeling excitement because it has worked for you based on the way you've coded it. However, let me explain why I think you may want to alter this section of code.

The way the code is written, it is error prone in the case of delays of the proper window popping up. For example, your script hits the next button to bring up one of the two windows. Right after that command, your WinActive() fires... BUT the window lagged when coming up so the WinActive() doesn't resolve as true. So instead, your script continues on with its normal operation not running any of your code for that extra window.

And on another note, it's advisable to use a WinActivate() followed by ControlCommand() to click on buttons for the installer, as some controls need to have the window in question in focus at the time the command is sent to interact with a control.


Spoiler

“Hello, ladies, look at your man, now back to me, now back at your man, now back to me. Sadly, he isn’t me, but if he stopped using ladies scented body wash and switched to Old Spice, he could smell like he’s me. Look down, back up, where are you? You’re on a boat with the man your man could smell like. What’s in your hand, back at me. I have it, it’s an oyster with two tickets to that thing you love. Look again, the tickets are now diamonds. Anything is possible when your man smells like Old Spice and not a lady. I’m on a horse.”

 

Share this post


Link to post
Share on other sites

Many thanks JDelaney and mechaflash213 - great help.

I will go away and read your advice a few times and see if I can improve my script.

I am very new to AutoIT and scripting but I am learning fast and appreciate the help.

Share this post


Link to post
Share on other sites

Having studied the above code I must admit I don't understand it. I do however want to improve my script and install process.

I have gone through the install again using Control View program by Yashied.

This time I have retrieved the Class, Instance, ID, Handle and Text of all control's and also the Title, Class, Handle and PID of all window's.

Which method will prove best to ensure the install process goes to plan?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0