How to handle optional windows in Autoit? - windows

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')

Related

Passing Command Line Argument to SwitchCase in AutoIt

I have a script that has a GUI and I have been running with a start button using the below code:
Case $StartButton
I would also like to try scheduling this using Windows TaskScheduler to run every morning at 8 AM EST. What would be the best way to add a condition to either start with the start button OR when TaskScheduler runs at 8 AM EST (or any specific time)? I am hesitant to just do 8 AM condition as it may increase processing a lot always looking at the time.
Essentially what I am looking to have happen is for my computer to auto-unlock (login?) using task scheduler and run this AutoIt script which has been compiled to exe.
FilePath is: C:\Users\robert\OneDrive\Desktop\TempFile.exe
Block of relevant code is below:
While 1
$nMsg = GUIGetMsg()
Switch $nMsg
Case $GUI_EVENT_CLOSE
Exit
Case $Save
SaveOptions()
Case $StartButton
;TAB1 of GUI
If WinExists("[CLASS: QT373947473845]") Then
$oBlah = WinGetHandle("[CLASS: QT373947473845]")
$BSLoc = WinGetPos ("[CLASS: QT373947473845]")
If $BSLoc[0] <> 0 or $BSLoc[1] <> 0 or $BSLoc[2] <> 800 or $BSLoc[3] <> 600 Then
WinSetState ( $oBlah, "", #SW_MINIMIZE )
sleep(500)
WinActivate($oBlah)
WinWaitActive($oBlah)
WinMove($oBlah, "", 0, 0, 800, 600)
sleep(2000)
Else
WinActivate($oBlah)
WinWaitActive($oBlah)
sleep(2000)
EndIf
Endif
EndSwitch
WEnd
I have thousands of lines of other code within the case but I tried to limit it as that portion is irrelevant
The Case $StartButton is the line where I am trying to do an OR if run by TaskManager. I have read you cannot do an OR function within a switch case but if you do 2 cases without a break it is the same thing?
I read some documentation and saw I can add a “/prim1=value” to the end of the command line and it will pass the prim1 argument to $CmdLine[0] but I can’t seem to get it working properly.
Review the documentation.
Particularly this part:
So if you were to use the compiled executable by passing commandline
parameters:
myProg.exe param1 "This is a string parameter" 99
$CmdLine[0] ; this equals 3 (because there are 3 command line parameters)
$CmdLine[1] ; This contains "param1".
$CmdLine[2] ; This contains "This is a string parameter".
$CmdLine[3] ; This contains 99.
So then just modify the code so that it behaves differently if $CmdLine[1] = something.
As for the switch case: that is inside of a message loop for the GUI and the code in the Case $StartButton part of the switch block is run when the start button is pressed and $nMsg is equal to the control ID of the start button ($StartButton).
If you want to run this code at some other time what I would do it just move all of that code into its own function:
Func onStartClick()
; start button code here
Endfunc
And then just call onStartClick() in the switch block:
$nMsg = GUIGetMsg()
Switch $nMsg
Case $StartButton
onStartClick()
Case $someOtherButton
; someOtherButton code...etc
EndSwitch
And then you can also call this function if there is a particular command line param (place this code before the Switch...EndSwitch block, not inside it):
If $CmdLine[0] >= 1 And $CmdLine[1] = "param1" then
; other code to run when started with "program.exe param1"
onStartClick()
EndIf
So the entire thing would look like this:
Func onStartClick()
; start button code here
Endfunc
If $CmdLine[0] >= 1 And $CmdLine[1] = "param1" then
; other code to run when started with "param1"
onStartClick()
EndIf
$nMsg = GUIGetMsg()
Switch $nMsg
Case $StartButton
onStartClick()
Case $someOtherButton
; someOtherButton code...etc
EndSwitch

Auto it how to check if window appears and close

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

Get start of line without taking soft line breaks into account

In a RichTextBox, when sending EM_LINEINDEX to get the index of the first character of a line, the index will be affected by soft line breaks. Consider the following text box:
Calling SendMessage hWnd, EM_LINEINDEX, 1, 0 will result in 25, while I would expect it to return 45 (line 1 should be "this is another line" not "and continues here").
Is there a way to get the real first char index of the second line using WinAPI calls?
This is from a working program. I play with right margin.
Sub mnuWordWrap_Click()
'On Error Resume Next
If txtNote.RightMargin = 0 Then
txtNote.RightMargin = &HFFFE&
mnuWordWrap.Checked = False
Else
txtNote.RightMargin = 0
mnuWordWrap.Checked = True
End If
txtNote.SetFocus
txtNote_SelChange
End Sub
In another program I do this, though this is Vista's RTF window (not a control so not the old ANSI version of RTF as in VB6)
If mnuViewWordWrap.Checked = True Then
Ret = SendMessageByVal(gRtfHwnd, EM_SETTARGETDEVICE, GetDC(gRtfHwnd), -1800)
If Ret = 0 Then ReportError "Form Resize", "Set Target Device"
Else
Ret = SendMessageByVal(gRtfHwnd, EM_SETTARGETDEVICE, GetDC(gRtfHwnd), 4000000)
If Ret = 0 Then ReportError "Form Resize", "Set Target Device"
End If

Navigate Shell command not working when the path includes an hash

I'm having problem using the Navigate Shell command when the path include an # sign.
; this will create 2 folders at the root of your C: drive
myPath1 := "C:\delete_me\"
myPath2 := "C:\delete#me\"
if !FileExist(myPath1)
FileCreateDir, %myPath1%
if !FileExist(myPath2)
FileCreateDir, %myPath2%
; make an Explorer active and press Alt-1 and Alt-2
return
!1::
strWinId := WinExist("A")
TrayTip, %myPath1%, %strWinId%
For pExp in ComObjCreate("Shell.Application").Windows
if (pExp.hwnd = strWinId)
try pExp.Navigate(myPath1)
return
!2::
strWinId := WinExist("A")
TrayTip, %myPath2%, %strWinId%
For pExp in ComObjCreate("Shell.Application").Windows
if (pExp.hwnd = strWinId)
try pExp.Navigate(myPath2)
return
Alt-1 works well. But, with Alt-2, the Navigate command returns "file:///C:/delete#me/ » not found.".
If there is no "/" after the "#" (eg myPath := "C:\delete#me"), it works. But this cannot be a solution because the destination path can be deeper in a subfolder (eg. "C:\delete#me\xyz").
I tried to encode the "#", replacing it with "%23", without success. Found nothing on the web or MSDN about that. Any idea?
[keywords: haskmark, hashtag, number sign or pound]
I have what looks to be a working solution for this, which I've also posted here:
4 options to change the current folder in Windows Explorer - Page 3 - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=5&t=526&p=153676#p153676
;links:
;Explorer Windows Manipulations - Page 5 - Scripts and Functions - AutoHotkey Community
;https://autohotkey.com/board/topic/19039-explorer-windows-manipulations/page-5#entry297581
;Navigate2 Method (IWebBrowser2)
;https://msdn.microsoft.com/en-us/library/aa752134(v=vs.85).aspx
;4 options to change the current folder in Windows Explorer - AutoHotkey Community
;https://autohotkey.com/boards/viewtopic.php?f=5&t=526
;windows - Navigate Shell command not working when the path includes an hash - Stack Overflow
;https://stackoverflow.com/questions/22868546/navigate-shell-command-not-working-when-the-path-includes-an-hash
;an AutoHotkey v1.1 script
;note: will create folder: %A_Desktop%\abc#def\abc#def
;q:: ;explorer - navigate to folder (tested on Windows 7)
WinGet, hWnd, ID, A
WinGetClass, vWinClass, % "ahk_id " hWnd
if !(vWinClass = "CabinetWClass") && !(vWinClass = "ExploreWClass")
return
vDir = %A_Desktop%\abc#def\abc#def
;vDir = %A_Desktop%\abc def\abc def
if !FileExist(vDir)
FileCreateDir, % vDir
DllCall("shell32\SHParseDisplayName", WStr,vDir, Ptr,0, PtrP,vPIDL, UInt,0, Ptr,0)
for oWin in ComObjCreate("Shell.Application").Windows
if (oWin.HWND = hWnd)
{
if !InStr(vDir, "#")
oWin.Navigate(vDir)
else
{
VarSetCapacity(SAFEARRAY, A_PtrSize=8?32:24, 0)
NumPut(1, SAFEARRAY, 0, "UShort")
NumPut(1, SAFEARRAY, 4, "UShort")
NumPut(vPIDL, SAFEARRAY, A_PtrSize=8?16:12, "Ptr")
NumPut(DllCall("shell32\ILGetSize", Ptr,vPIDL, UInt), SAFEARRAY, A_PtrSize=8?24:16, "Int")
oWin.Navigate2(ComObject(0x2011,&SAFEARRAY))
DllCall("shell32\ILFree", Ptr,vPIDL)
}
break
}
return
If you want to open a new window, there's no need for COM or unreliable workarounds: just run the folder.
Run C:\delete#me
If you want to open the path in an existing window which is already active, the simplest and most effective workaround is this:
SendInput {F4}{Esc}{Raw}C:\delete#me`n
So in the context of your script, you could use the following function to work around the # when it is present:
Navigate(pExp, myPath2)
;...
Navigate(Exp, Path)
{
if RegExMatch(Path, "#.*\\")
SendInput {F4}{Esc}{Raw}%Path%`n
else
Exp.Navigate(Path)
}
Unfortunately, there does not seem to be a solution to this. Shell.Application Navigate command fails if the path includes a hash (# as in C:\C#Projects).
Using AutoHotkey, the workaround would be to rely on the "second best" approach as identified by the tests in this thread: http://ahkscript.org/boards/viewtopic.php?f=5&t=526.
run, Explorer.exe
Sleep, 500
strFolder := A_ScriptDir
Send, {F4}{Esc}
Sleep, 500
ControlSetText, Edit1, C:\delete#me, A
ControlSend, Edit1, {Enter}, A
When I saw that Navigate couldn't handle hash, I was shocked,
but sure enough I replicated the error.
I thought I'd try the short form path just in case. It works!
if vDir contains #
Loop, %vDir%, 2, 0 ;(0/1/2=files/both/folders, 0/1=recurse no/yes)
vDir := A_LoopFileShortPath
The following approach doesn't require a visible address bar, or SendInput,
also the previous navigation history is maintained.
In the worst-case scenario of a hash in the short-form path of the dir above the target dir,
a go-between folder is used which is navigated to.
A link is created there, invoked, and deleted.
Below, the workaround code is indented, to separate it from the standard code.
A hotkey of ctrl+q, when an Explorer window is active, launches the script.
-
^q:: ;explorer - navigate to directory (use go-between dir if short-form path of dir above target contains #)
WinGet, hWnd, ID, A
WinGetClass, vWinClass, ahk_id %hWnd%
if vWinClass not in CabinetWClass,ExploreWClass
Return
vDir2 = %A_Desktop%\Go-Between ;go-between dir
vDir3 = C:\delete#me ;target dir
if (SubStr(vDir3, 1-1) = "\")
vDir3 := SubStr(vDir3, 1, -1)
if !InStr(FileExist(vDir3), "D")
Return
vPathLnk := ""
if vDir3 contains #
Loop, %vDir3%, 2, 0 ;(0/1/2=files/both/folders, 0/1=recurse no/yes)
vDir3 := A_LoopFileShortPath
;vDir4 is the short-form path of the dir above the target
;paths of problem target dirs are of the form: *#*\*
;where there is at least one hash with a backslash to its right
SplitPath, vDir3, , vDir4
if vDir4 contains #
{
if !InStr(FileExist(vDir2), "D")
FileCreateDir, %vDir2%
if !InStr(FileExist(vDir2), "D")
{
MsgBox error`, go-between dir not found:`r`n%vDir2%
Return
}
vNameLnk = Go-Between.lnk
vPathLnk = %vDir2%\%vNameLnk%
FileCreateShortcut, %vDir3%, %vPathLnk%
}
for oWin in ComObjCreate("Shell.Application").Windows
if (hWnd = oWin.Hwnd)
{
vDir1 := oWin.Document.Folder.Self.Path
if (vDir1 = vDir3)
break
if vDir3 contains #
{
if !(vDir1 = vDir2)
oWin.Navigate(vDir2)
while !(oWin.ReadyState = 4)
Sleep 10
oItem := oWin.Document.Folder.Items.Item(vNameLnk)
oItem.InvokeVerbEx("open")
break
}
oWin.Navigate(vDir3)
break
}
oWin := ""
if !(vPathLnk = "")
FileRecycle, %vPathLnk% ;send to recycle bin
;if !(vPathLnk = "")
;FileDelete, %vPathLnk% ;delete
Return

AutoHotkey able to capture firefox tab?

It is a bit beyond of my knowledge, so I copy&pasted the whole script.
But I was rejected with a message, which reads, (Firefox version is 28.0) Anybody please help me.
Error: Call to nonexistent function.
Specifically: Acc_Get( ... ...
SetTitleMatchMode 2
WinGet, windows, List, Mozilla Firefox
Loop %windows% {
hwnd := windows%A_Index%
;// Acc_Get(Cmd, ChildPath="", ChildID=0, WinTitle="", WinText="", ExcludeTitle="", ExcludeText="")
page_tab_list := Acc_Get("object", "application.grouping2.property_page.tool_bar3.page_tab_list", "", "ahk_id" hwnd)
For Each, tab in Acc_Children(page_tab_list)
if tab.accName(0) = "https://www.apple.com/" {
tab.accDoDefaultAction(0) ;// remove line to NOT activate tab
WinActivate ahk_id %hwnd%
break 2
}
}
This script simply walks through all tabs until it finds the correct one, via the page title in the window title. Sleep timer can be adjusted.
SetTitleMatchMode 2
needle := "Stack Overflow"
WinActivate, Firefox
Loop {
WinGetTitle, title
IfWinNotActive, Firefox
break
if (InStr(title,needle))
Break
Else
send ^{PgUp}
sleep 50
}
You didn't take all the dependencies from the source. You are missing the required Acc Library.
; Acc.ahk https://github.com/sancarn/ACC.AHK/blob/master/AccV2.ahk
; ACC Tutorial: https://www.autohotkey.com/boards/viewtopic.php?f=7&t=40590

Resources