Auto it how to check if window appears and close - window

How do I check if a specific windoww appears in Autoit.
At the moment I am running with Auto it Adobe After Effect,
so far so good.
The problem is that a warning message pops up if the user does not have quick time installed.
Now I want to check if that window appears and is active and then close it.
So far I have this but did not work:
Local $iPID = Run("C:\Program Files\Adobe\Adobe After Effects CC 2015\Support Files\AfterFX.exe", "", #SW_SHOWMAXIMIZED)
WinWait("[CLASS:AfterEffects]", "", 1000)
Sleep(200000)
; if qicktime warning eror appears
If WinExists ("DroverLord - Window Class", "") Then
Send ("{ENTER}")
EndIf

Does this help?
Opt("WinDetectHiddenText", 1) ;0=don't detect, 1=do detect
Opt("WinSearchChildren", 1) ;0=no, 1=search children also
Opt("WinTextMatchMode", 1) ;1=complete, 2=quick
Opt("WinTitleMatchMode", 2) ;1=start, 2=subStr, 3=exact, 4=advanced, -1 to -4=Nocase
#include<Date.au3>
Local $iPID = Run("C:\Program Files\Adobe\Adobe After Effects CC 2015\Support Files\AfterFX.exe", "", #SW_SHOWMAXIMIZED)
If #error Then
ConsoleWrite('ERROR' & #CRLF)
Exit(0)
EndIf
Global $end = False
Do
; if qicktime warning eror appears
If WinExists("DroverLord - Window Class", "") Then
ConsoleWrite('!FOUND ' & _NowTime() & #CRLF)
Send("{ENTER}") ;close?
WinClose("DroverLord - Window Class", "") ; this
WinKill("DroverLord - Window Class", "") ; or this
$end = True
EndIf
Until $end

Here is an some example code of what you are trying to do:
Local $fDiff
Local $sAfterFXPath = "C:\Program Files\Adobe\Adobe After Effects CC 2015\Support Files\AfterFX.exe"
If FileExists($sAfterFXPath) Then
Local $iPID = Run($sAfterFXPath, "", #SW_SHOWMAXIMIZED)
;no need to call WinExists becuase you are waiting for it to exist and be active with WinActivate
Local $hTimer = TimerInit() ; Begin the timer and store the handle in a variable.
Do
$fDiff = TimerDiff($hTimer)
Until WinActive("Title you are looking for") Or $fDiff >= 30000 ;<<<will exit loop when the window is active or after 30 seconds
If WinActive("Title you are looking for") Then
;Closes the window now that it is active
WinClose("Title you are looking for")
Else
MsgBox(0, "", "The window was never active.")
EndIf
Else
MsgBox(0, "", "File path not found. Do something else...")
EndIf

Related

How to read value from slider control?

I used simplespy.au3 to target a slider control in the Windows settings window using _UIA_action(). Asking the user to input a value I send left and right keys for the slider to move.
But I don't know how to get the current value of my slider. I tried GUICtrlRead() but it doesn't work. How do I get the current value of a slider control?
My code:
#RequireAdmin
#include <IE.au3>
#include <MsgBoxConstants.au3>
#include <GuiSlider.au3>
#include <GUIConstants.au3>
#include "UISpy\UIAWrappers\UIAWrappers.au3"
Slider()
Func Slider()
;User Input
$Default = ""
$input = ""
While 1
$input = InputBox("Brightness", "Set Brightness to:", "", " M", -1, -1)
If #error Then ExitLoop
If $input < 0 Or $input > 100 Then
MsgBox(48, "Error!", "Minimum value for brightness is 0 and the Maximum brightness is 100")
$Default = $input
ContinueLoop
ElseIf StringLen($input) > 0 Or $input < 100 Then
ExitLoop
EndIf
If #error = 1 Then
Exit
EndIf
WEnd
;Start automation
Local $iTimeout = 1
Local $hWnd = WinWait("[Class:Shell_TrayWnd]", "", "[CLASS:Button; INSTANCE:1]")
ControlClick($hWnd, "", "[CLASS:Button; INSTANCE:1]") ;open the start menu
Send("Display Settings", 10) ;Type the Display Settings in the start menu
Sleep(1000)
Send("{ENTER}")
AutoItSetOption("MustDeclareVars", 1)
Local $oP2 = _UIA_getObjectByFindAll($UIA_oDesktop, "Title:=Settings;controltype:=UIA_WindowControlTypeId;class:=ApplicationFrameWindow", $treescope_children)
_UIA_Action($oP2, "setfocus")
Local $oP1 = _UIA_getObjectByFindAll($oP2, "Title:=Settings;controltype:=UIA_WindowControlTypeId;class:=Windows.UI.Core.CoreWindow", $treescope_children)
_UIA_Action($oP1, "setfocus")
Local $oP0 = _UIA_getObjectByFindAll($oP1, "Title:=;controltype:=UIA_PaneControlTypeId;class:=ScrollViewer", $treescope_children)
;First find the object in the parent before you can do something
; $oUIElement=_UIA_getObjectByFindAll("Changebrightness.mainwindow", "title:=Change brightness;ControlType:=UIA_SliderControlTypeId", $treescope_subtree)
Local $oUIElement = _UIA_getObjectByFindAll($oP0, "title:=Change brightness;ControlType:=UIA_SliderControlTypeId", $treescope_subtree)
_UIA_action($oUIElement, "setfocus")
Send("{LEFT $input}"`enter code here`)
Sleep(1000)
Local $value = GUICtrlRead($oUIElement)
MsgBox($MB_SYSTEMMODAL, "", "Brightness is at: " & $value, $iTimeout)
Local $setValue = GUICtrlSetData($oUIElement, 50)
;UI for verification
MsgBox(0, "Change Brightness", "Brightness Changed.", $iTimeout)
Sleep(1000)
WinClose("Settings") ;Close the active window
EndFunc ;==>Slider
Don't manipulate the slider. Use the WinAPI instead: _WinAPI_SetDeviceGammaRamp.

Running multiple identical applications

Tell me why it does not work? I searched, but did not find how to run several identical applications, so that you can then work with each separately.
The script works, starts the first window, moves it, then the second window starts and the first moves along the second coordinate, and the second one does not move. What is the problem?
Run('c:\Program Files\CPUID\CPU-Z\cpuz.exe')
$hWnd = WinWait("[TITLE:CPU-Z; INSTANCE:1]", "", 0)
If Not $hWnd Then
MsgBox(4096, 'Сообщение', 'Окно не найдено, завершаем работу скрипта')
Exit
EndIf
Sleep(400)
WinMove($hWnd, "", 0, 645)
Run('c:\Program Files\CPUID\CPU-Z\cpuz.exe')
$hWnd2 = WinWaitActive("[TITLE:CPU-Z; INSTANCE:2]", "", 0)
If Not $hWnd2 Then
MsgBox(4096, 'Сообщение', 'Окно не найдено, завершаем работу скрипта')
Exit
EndIf
Sleep(400)
WinMove($hWnd2, "", 405, 645)
How to correctly write such a script?
...and the second one does not move. What is the problem?
Script generates identical $hWnd and $hWnd2 tied to the initial window, which you can check by outputting variables with MsgBox() or _DebugOut() or whatever you like. Looks like INSTANCE property doesn't work well in current scenario, so WinWait() searches window using title only and the second call finds the same window as the first one.
How to correctly write such a script?
Well, I have less than one week of AutoIt experience, so don't hit me hard, but here is my version:
Run('c:\Program Files\CPUID\CPU-Z\cpuz.exe')
Global $hWnd = WinWait("CPU-Z", "", 0)
If Not $hWnd Then
MsgBox(4096, 'Сообщение', 'Окно не найдено, завершаем работу скрипта')
Exit
EndIf
Sleep(400)
WinMove($hWnd, "", 0, 645)
Run('c:\Program Files\CPUID\CPU-Z\cpuz.exe')
Global $hWnd2 = Null
;wait until there are two windows with the same title
Do
Sleep(10)
Global $aList = WinList("CPU-Z")
Until $aList[0][0] > 1
For $i = 1 To $aList[0][0]
If $aList[$i][1] <> $hWnd Then
$hWnd2 = $aList[$i][1]
EndIf
Next
If Not $hWnd2 Then
MsgBox(4096, 'Сообщение', 'Окно не найдено, завершаем работу скрипта')
Exit
EndIf
Sleep(400)
WinMove($hWnd2, "", 405, 645)
EDIT
Bonus: packed repetitive part of the script into function for easy use with multiple windows:
Global $aKnownHandles[1] ;array storing all known win handles
Global $iCounter = 0 ;keeps track of array size
AddInstance(0, 645)
AddInstance(405, 645)
AddInstance(810, 645)
AddInstance(1215, 645)
AddInstance(0, 345)
AddInstance(405, 345)
AddInstance(810, 345)
AddInstance(1215, 345)
AddInstance(0, 50)
AddInstance(405, 50)
AddInstance(810, 50)
AddInstance(1215, 50)
Func AddInstance($x, $y)
Run('c:\Program Files\CPUID\CPU-Z\cpuz.exe')
Do
Sleep(1)
Local $aWinList = WinList("CPU-Z")
Until $aWinList[0][0] > $iCounter
Local $hNewHandle = Null
;for each handle in list of windows ($aWinList)
;check if it matches any item in list of known handles ($aKnownHandles)
;If not, put handle into $hNewHandle variable
For $i = 1 To $aWinList[0][0]
Local $bHandleKnown = false
For $j = 0 To $iCounter-1
If $aWinList[$i][1] == $aKnownHandles[$j] Then
$bHandleKnown = true
ExitLoop
EndIf
Next
If NOT $bHandleKnown Then
$hNewHandle = $aWinList[$i][1]
ExitLoop
EndIf
Next
If Not $hNewHandle Then
MsgBox(4096, 'Сообщение', 'Окно не найдено, завершаем работу скрипта')
Exit
EndIf
Sleep(400)
WinMove($hNewHandle, "", $x, $y)
ReDim $aKnownHandles[$iCounter+1] ;resize array
$aKnownHandles[$iCounter] = $hNewHandle ;add new handle to list of known
$iCounter += 1 ;update counter
EndFunc

How to handle optional windows in Autoit?

I am automating a software installation in Windows7 using AutoIt.
During the installation, in between if a error window appears. I want to click ENTER.
If the error window not appears then I should NOT do anything. Simply its should go to the next section.
I have tried "WinActive and WinWaitActive" But its waiting for the window to appear. If window not appears its not going to the next screen.
Any idea how to handle this situation?
Do a while loop:
$w = 0
While($w = 0)
If(WinActive("ERROR WINDOW"))Then
Send("{ENTER}")
$w = 1
ElseIf(ControlGetText("YOUR WINDOW", "", "[CLASS:Static; INSTANCE:2]") <> "SOME TEXT") Then
$w = 1
;and something else
EndIf
Sleep(1000)
WEnd
AdlibRegister() is the right choice. From the help file:
"... typically to check for unforeseen errors. For example, you could use adlib in a script which causes an error window to pop up unpredictably."
Each 100 ms (may be adjusted) the function is called to check the appearing of your error dialog:
Global $sErrorWindow = 'ErrorDialogName'
Global $iDelayHowOftenDoTheFunctionCall = 100
AdlibRegister('_isErrorWindowDisplayed', $iDelayHowOftenDoTheFunctionCall)
Func _isErrorWindowDisplayed()
If WinActive($sErrorWindow) <> 0 Then
WinActivate($sErrorWindow) ; just to be sure that the ENTER command is on the correct window/dialog
; either do
Send('{ENTER}')
; or
ControlClick('title', 'text', 'controlID')
EndIf
EndFunc
; do your software installation processing here
; ...
; ...
; don't forget to unregister the function at the end
AdlibUnRegister('_isErrorWindowDisplayed')

How to use PixelSearch() on inactive windows?

Because of the $hwnd parameter I assume PixelSearch() should work on an inactive window but I can't make it do so. When another window is put in front of the one to search, it fails.
My script :
$hwnd = WinGetHandle("[CLASS:MSPaintApp]")
$Cor = PixelSearch(0, 0, #DesktopWidth, #DesktopHeight, 0x39B6EF, 0, 1, $hwnd)
If Not #error Then
MouseMove($Cor[0], $Cor[1])
Else
MsgBox(0, "", #error)
EndIf
How can I make this work on an inactive window?
Simple fix of making sure that the window you want to search on is active (If I read the question correctly). The WinActive checks to see if the window is active, and if it is 0 (not active). Then, we active the window using WinActivate.
Local $hwnd, $Cor
$hwnd = WinGetHandle("[CLASS:MSPaintApp]")
If WinActive($hwnd) = 0 Then
WinActivate($hwnd)
EndIf
$Cor = PixelSearch(0, 0, #DesktopWidth, #DesktopHeight, 0x39B6EF, 0, 1, $hwnd)
If Not #error Then
MouseMove($Cor[0], $Cor[1])
Else
MsgBox(0, "", #error)
EndIf

Best way to wrap rsync progress in a gui?

I use rsync to synchronize files to Windows clients in a server agnostic way. What methods are available to send the progress of rsync to the parent process for display in a gui progress bar?
I imagine two or three choices exist. (1) Watch STDOUT (2) Watch rsync.exe log file, similar to unix tail (3) Watch rsync console output in memory.
Which one is best/preferred?
For this type of tasks, I use my own AutoIt script (freeware, Windows only). The script redirects the standard output into a graphical window, displaying it with the ability to scroll back, etc (very useful in long processes like XCOPYs / PKZIPs to check if any error did happen).
I use AutoIt because it's free, very easy to use, and can compile quickly into an .EXE. I think it's an excellent alternative to a complete programming language for this type of tasks. The downside is that it's for Windows only.
$sCmd = "DIR E:\*.AU3 /S" ; Test command
$nAutoTimeout = 10 ; Time in seconds to close window after finish
$nDeskPct = 60 ; % of desktop size (if percent)
; $nHeight = 480 ; height/width of the main window (if fixed)
; $nWidth = 480
$sTitRun = "Executing process. Wait...." ;
$sTitDone = "Process done" ;
$sSound = #WindowsDir & "\Media\Ding.wav" ; End Sound
$sButRun = "Cancel" ; Caption of "Exec" button
$sButDone = "Close" ; Caption of "Close" button
#include <GUIConstants.au3>
#include <Constants.au3>
#Include <GuiList.au3>
Opt("GUIOnEventMode", 1)
if $nDeskPct > 0 Then
$nHeight = #DesktopHeight * ($nDeskPct / 100)
$nWidth = #DesktopWidth * ($nDeskPct / 100)
EndIf
If $CmdLine[0] > 0 Then
$sCmd = ""
For $nCmd = 1 To $CmdLine[0]
$sCmd = $sCmd & " " & $CmdLine[$nCmd]
Next
; MsgBox (1,"",$sCmd)
EndIf
; AutoItSetOption("GUIDataSeparatorChar", Chr(13)+Chr(10))
$nForm = GUICreate($sTitRun, $nWidth, $nHeight)
GUISetOnEvent($GUI_EVENT_CLOSE, "CloseForm")
$nList = GUICtrlCreateList ("", 10, 10, $nWidth - 20, $nHeight - 50, $WS_BORDER + $WS_VSCROLL)
GUICtrlSetFont (-1, 9, 0, 0, "Courier New")
$nClose = GUICtrlCreateButton ($sButRun, $nWidth - 100, $nHeight - 40, 80, 30)
GUICtrlSetOnEvent (-1, "CloseForm")
GUISetState(#SW_SHOW) ;, $nForm)
$nPID = Run(#ComSpec & " /C " & $sCmd, ".", #SW_HIDE, $STDOUT_CHILD)
; $nPID = Run(#ComSpec & " /C _RunErrl.bat " & $sCmd, ".", #SW_HIDE, $STDOUT_CHILD) ; # Con ésto devuelve el errorlevel en _ERRL.TMP
While 1
$sLine = StdoutRead($nPID)
If #error Then ExitLoop
If StringLen ($sLine) > 0 then
$sLine = StringReplace ($sLine, Chr(13), "|")
$sLine = StringReplace ($sLine, Chr(10), "")
if StringLeft($sLine, 1)="|" Then
$sLine = " " & $sLine
endif
GUICtrlSetData ($nList, $sLine)
_GUICtrlListSelectIndex ($nList, _GUICtrlListCount ($nList) - 1)
EndIf
Wend
$sLine = " ||"
GUICtrlSetData ($nList, $sLine)
_GUICtrlListSelectIndex ($nList, _GUICtrlListCount ($nList) - 1)
GUICtrlSetData ($nClose, $sButDone)
WinSetTitle ($sTitRun, "", $sTitDone)
If $sSound <> "" Then
SoundPlay ($sSound)
EndIf
$rInfo = DllStructCreate("uint;dword") ; # LASTINPUTINFO
DllStructSetData($rInfo, 1, DllStructGetSize($rInfo));
DllCall("user32.dll", "int", "GetLastInputInfo", "ptr", DllStructGetPtr($rInfo))
$nLastInput = DllStructGetData($rInfo, 2)
$nTime = TimerInit()
While 1
If $nAutoTimeout > 0 Then
DllCall("user32.dll", "int", "GetLastInputInfo", "ptr", DllStructGetPtr($rInfo))
If DllStructGetData($rInfo, 2) <> $nLastInput Then
; Tocó una tecla
$nAutoTimeout = 0
EndIf
EndIf
If $nAutoTimeout > 0 And TimerDiff ($nTime) > $nAutoTimeOut * 1000 Then
ExitLoop
EndIf
Sleep (100)
Wend
Func CloseForm()
Exit
EndFunc
.NET has a pretty straight forward way to read and watch STDOUT.
I guess this would be the cleanest way, since it is not dependent on any external files, just the path to rsync. I would not be too surprised if there is a wrapper library out there either. If not, write and open source it :)
I've built my own simple object for this, I get a lot of reuse out of it, I can wrap it with a cmdline, web page, webservice, write output to a file, etc---
The commented items contain some rsync examples--
what I'd like to do sometime is embed rsync (and cygwin) into a resource & make a single .net executable out of it--
Here you go:
Imports System.IO
Namespace cds
Public Class proc
Public _cmdString As String
Public _workingDir As String
Public _arg As String
Public Function basic() As String
Dim sOut As String = ""
Try
'Set start information.
'Dim startinfo As New ProcessStartInfo("C:\Program Files\cwRsync\bin\rsync", "-avzrbP 192.168.42.6::cdsERP /cygdrive/s/cdsERP_rsync/gwy")
'Dim startinfo As New ProcessStartInfo("C:\Program Files\cwRsync\bin\rsync", "-avzrbP 10.1.1.6::user /cygdrive/s/cdsERP_rsync/gws/user")
'Dim startinfo As New ProcessStartInfo("C:\windows\system32\cscript", "//NoLogo c:\windows\system32\prnmngr.vbs -l")
Dim si As New ProcessStartInfo(_cmdString, _arg)
si.UseShellExecute = False
si.CreateNoWindow = True
si.RedirectStandardOutput = True
si.RedirectStandardError = True
si.WorkingDirectory = _workingDir
' Make the process and set its start information.
Dim p As New Process()
p.StartInfo = si
' Start the process.
p.Start()
' Attach to stdout and stderr.
Dim stdout As StreamReader = p.StandardOutput()
Dim stderr As StreamReader = p.StandardError()
sOut = stdout.ReadToEnd() & ControlChars.NewLine & stderr.ReadToEnd()
'Dim writer As New StreamWriter("out.txt", FileMode.CreateNew)
'writer.Write(sOut)
'writer.Close()
stdout.Close()
stderr.Close()
p.Close()
Catch ex As Exception
sOut = ex.Message
End Try
Return sOut
End Function
End Class
End Namespace
Check out DeltaCopy. It is a Windows GUI for rsync.
Check NAsBackup Its open source software that give Windows user Rsync GUI using Watch STDOUT.

Resources