To start, this is not another thread asking for help because I can't get ImageSearch to work at all.
Script Use: With Oracle Applications in use in a manufacturing plant, being used to log transfers of subassemblies along a production line.
Script Concept: Extrapolate necessary key hits based off of minimal user input. Look for visual cues on the screen to verify that Oracle Applications is responding in the desired fashion--if not, cancel the operations.
My basic method is to hit several keys to do something in Oracle Applications, and then look for the desired response. I use a looped ImageSearch over 10 seconds that looks for an image fragment. As soon as the desired image fragment is found (for example, the window title of a message box that should pop up) the script proceeds.
Since the Oracle Applications I have uses a Java interface, everything inside of it is transparent to Autohotkey--it's all one window. There's no other way to detect what's going on inside the program besides ImageSearch, in case anyone wonders. (Or if there is, it's waaay over my head.)
So, what's the problem?
Well, the script works 100% beautifully the first time. I enter my data into the custom Autohotkey GUI I made, my "Log Job" button triggers a subroutine (Sub_LogJob) that calls a custom function (F_CheckLog) I have. The custom function runs all the way through successfully, using 10 or so instances of ImageSearch to verify things are dandy along the way. Everything goes fine in Oracle Applications and in the end I get a MsgBox saying "Job Successfully Logged."
The
problem is that when I call up the GUI again, enter data and try to run it, it doesn't work a second time.
The "Log Job" button triggers the Sub_LogJob subroutine.
The Sub_LogJob subroutine calls the F_CheckLog function.
But as soon as the F_CheckLog function tries to use ImageSearch, I get an ErrorLevel 2, meaning that Autohotkey couldn't search for my image. This is usually some sort of formatting problem, like leaving the ".bmp" off of the image name. But that can't be, because my script just used that image successfully 30 seconds ago.
Why is this happening?
Scripts below.
Code:
;
; AutoHotkey Version: 1.x
; Language: English
; Platform: WinXP
; Author: Matthew
;
; Script Function:
; MERLIN CENTRAL FUNCTION LIBRARY
; Set of useful scripts for interacting with other programs.
; Additionally useful: FileInstall, Source, Dest, Overwrite?
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;GLOBAL DEFINITIONS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;This section defines some global variables for simplicity's sake.
SysGet, Sys_ScreenWidth, 78
SysGet, Sys_ScreenHeight, 79
V_Clipboard := ""
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;FUNCTIONS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;This section contains all the functions.
MF_ErrorClear()
{
FileDelete, %A_ScriptName%ErrorLog.txt
}
MF_ErrorLog(V_ErrorText, V_Fatal)
{
FileAppend, %V_ErrorText%`n, %A_ScriptName%ErrorLog.txt
If (V_Fatal = true)
{
MsgBox %V_ErrorText%
Run %A_ScriptName%ErrorLog.txt
exit
}
}
MF_Copy(ByRef V_Variable)
{
clipboard =
V_Clipboard =
send ^c
clipwait, 5
If (ErrorLevel = 1)
{
ErrorMsg := "MF_Copy (" . V_Variable . ") using Copy/Clipwait could not retrieve text."
MF_ErrorLog(ErrorMsg, false)
return 0
}
V_Clipboard = %clipboard%
V_Variable = %V_Clipboard%
return 1
}
MF_CopyCell(ByRef V_Variable)
{
clipboard =
V_Clipboard =
send {home}+{end}^c
clipwait, 5
If (ErrorLevel = 1)
{
ErrorMsg := "MF_CopyCell (" . V_Variable . ") using Copy/Clipwait could not retrieve text."
MF_ErrorLog(ErrorMsg, false)
return 0
}
V_Clipboard = %clipboard%
V_Variable = %V_Clipboard%
return 1
}
MF_CopyXCell(ByRef V_Variable)
{
clipboard =
V_Clipboard =
send {f2}{home}+{end}^c
clipwait, 5
If (ErrorLevel = 1)
{
ErrorMsg := "MF_CopyXCell (" . V_Variable . ") using Copy/Clipwait could not retrieve text."
MF_ErrorLog(ErrorMsg, false)
return 0
}
send {escape}
V_Clipboard = %clipboard%
V_Variable = %V_Clipboard%
return 1
}
MF_Tabover(V_Window)
{
WinActivate, %V_Window%
WinWaitActive, %V_Window%, , 5
If (ErrorLevel = 1)
{
ErrorMsg := "MF_Tabover (" . V_Window . ") using WinActivate/WinWaitActive could not activate the window."
MF_ErrorLog(ErrorMsg, false)
return 0
}
Else
return 1
}
MF_GetImagePos(V_Filename, ByRef V_CX, ByRef V_CY)
{
global Sys_ScreenWidth
global Sys_ScreenHeight
ImageSearch, V_CX, V_CY, 0, 0, %Sys_ScreenWidth%, %Sys_ScreenHeight%, %V_Filename%
If (ErrorLevel = 2)
{
ErrorMsg := "MF_GetImagePos using Imagesearch (" . V_CX . ", " . V_CY . ", 0, 0, " . Sys_ScreenWidth . ", " . Sys_ScreenHeight . ", " . V_Filename . ") could not search for the image."
MF_ErrorLog(ErrorMsg, false)
return 2
}
Else If (ErrorLevel = 1)
{
ErrorMsg := "MF_GetImagePos using Imagesearch (" . V_CX . ", " . V_CY . ", 0, 0, " . Sys_ScreenWidth . ", " . Sys_ScreenHeight . ", " . V_Filename . ") could not find the image."
MF_ErrorLog(ErrorMsg, false)
return 0
}
Else
return 1
}
MF_ClickImage(V_Filename, V_PlusX, V_PlusY)
{
V_Result := MF_GetImagePos(V_Filename, C_TEMPX, C_TEMPY)
If (V_Result = 2)
{
If (ErrorMsg := "")
ErrorMsg := "MF_ClickImage (" . V_Filename . ", " . V_PlusX . ", " . V_PlusY . ") using MF_GetImagePos (" . V_Filename . ", " . C_TEMPX . ", " . C_TEMPY . ") could not retrieve the image position."
MF_ErrorLog(ErrorMsg, false)
return 0
}
C_TEMPX += %V_PlusX%
C_TEMPY += %V_PlusY%
MouseClick, left, %C_TEMPX%, %C_TEMPY%
return 1
}
MF_WaitForImage(V_Image, V_Seconds)
{
If (V_Seconds = 0)
V_Seconds = 10
loop, %V_Seconds%
{
V_Result := MF_GetImagePos(V_Image, C_TEMPX, C_TEMPY)
If (V_Result = 1)
return 1
Else If (V_Result = 2)
{
ErrorMsg := "MF_WaitForImage (" . V_Image . ", " . V_Seconds . ") using MF_GetImagePos (" . V_Image . ", " . C_TEMPX . ", " . C_TEMPY . ") could not wait for the image."
MF_ErrorLog(ErrorMsg, false)
return 0
}
Else
If (A_Index > V_Seconds)
{
ErrorMsg := "MF_WaitForImage (" . V_Image . ", " . V_Seconds . ") using MF_GetImagePos (" . V_Image . ", " . C_TEMPX . ", " . C_TEMPY . ") could not find the image after " . V_Seconds . " seconds."
MF_ErrorLog(ErrorMsg, false)
return 0
}
sleep 1000
}
}
MF_WaitForImage2(V_Image1, V_Image2, V_Seconds)
{
If (V_Seconds = 0)
V_Seconds = 10
loop, %V_Seconds%
{
V_Result := MF_GetImagePos(V_Image1, C_TEMPX, C_TEMPY)
If (V_Result = 1)
return 1
V_Result := MF_GetImagePos(V_Image2, C_TEMPX, C_TEMPY)
If (V_Result = 1)
return 2
If (A_Index > V_Seconds)
{
ErrorMsg := "MF_WaitForImage2 (" . V_Image1 . ", " . V_Image2 . ") using MF_GetImagePos (" . V_Image1 . ", " . C_TEMPX . ", " . C_TEMPY . ") and MF_GetImagePos (" . V_Image2 . ", " . C_TEMPX . ", " . C_TEMPY . ") could not find the image after " . V_Seconds . " seconds."
MF_ErrorLog(ErrorMsg, false)
return 0
}
}
}
Code:
;
; AutoHotkey Version: 1.x
; Language: English
; Platform: WinXP
; Author: Matthew
;
; Script Function:
; Merlin AutoLog Script
; Intended to automate Oracle logging.
;
#SingleInstance force
#NoEnv
SendMode Input
SetWorkingDir %A_ScriptDir%
OnExit, ExitSub
FileInstall, MERLIN CFL.ahk, MERLIN CFL.ahk
#Include MERLIN CFL.ahk
;;;;;;;;;;
;Objects
;;;;;;;;;;
IniFile := SubStr(A_ScriptName, 1, InStr(A_ScriptName, ".ahk", false, 1)-1) . ".ini"
Focus_MoveTrans = AutoLog Focus MoveTrans.PNG
Focus_MoveTransClear = AutoLog Focus MoveTransClear.PNG
Focus_MoveTransType = AutoLog Focus MoveTransType.PNG
Focus_MoveTransOperations = AutoLog Focus MoveTransOperations.PNG
Focus_MoveTransError = AutoLog Focus MoveTransError.PNG
Focus_MoveTransError2 = AutoLog Focus MoveTransError2.PNG
Click_MoveTransAvailable = AutoLog Click MoveTransAvailable.PNG
;;;;;;;;;;
;Functions
;;;;;;;;;;
F_BasicLog(V_JobNum, V_Type, V_FromSeq, V_FromStep, V_ToSeq, V_ToStep, V_Over, V_Quantity)
{
MF_WaitForImage(Focus_MoveTransClear, 0)
send %V_JobNum%{tab}
If (V_Type = 1)
send !m{tab}%V_FromSeq%{tab}%V_FromStep%{tab}%V_ToSeq%{tab}%V_ToStep%{tab}
Else If (V_Type = 2)
send !c{tab}%V_FromSeq%{tab}%V_FromStep%{tab}
Else If (V_Type = 3)
send !u{tab}%V_ToSeq%{tab}%V_ToStep%
If (V_Type <> 3 and V_Over = true)
send {space}
send {tab}%V_Quantity%{enter}
}
F_CheckLog(V_JobNum, V_Type, V_FromSeq, V_FromStep, V_ToSeq, V_ToStep, V_Over, V_Quantity, V_AutoOver, V_CheckComp)
{
Global Focus_MoveTrans
Global Focus_MoveTransClear
Global Focus_MoveTransType
Global Focus_MoveTransOperations
Global Focus_MoveTransError
Global Focus_MoveTransError2
Global Click_MoveTransAvailable
V_Result := MF_WaitForImage(Focus_MoveTrans, 0)
If (V_Result = 0)
{
ErrorMsg := "F_CheckLog (" . V_JobNum . ", " . V_Type . ", " . V_FromSeq . ", " . V_FromStep . ", " . V_ToSeq . ", " . V_ToStep . ", " . V_Over . ", " . V_Quantity . ", " . V_AutoOver . ", " . V_CheckComp . ") using MF_WaitForImage (Focus_MoveTrans, 0) failed."
MF_ErrorLog(ErrorMsg, false)
return 0
}
V_Result := MF_WaitForImage(Focus_MoveTransClear, 0)
If (V_Result = 0)
{
ErrorMsg := "F_CheckLog (" . V_JobNum . ", " . V_Type . ", " . V_FromSeq . ", " . V_FromStep . ", " . V_ToSeq . ", " . V_ToStep . ", " . V_Over . ", " . V_Quantity . ", " . V_AutoOver . ", " . V_CheckComp . ") using MF_WaitForImage (Focus_MoveTransClear, 0) failed."
MF_ErrorLog(ErrorMsg, false)
return 0
}
send %V_JobNum%{tab}
V_Result := MF_WaitForImage2(Focus_MoveTransType, Focus_MoveTransError, 0)
If (V_Result = 0)
{
ErrorMsg := "F_CheckLog (" . V_JobNum . ", " . V_Type . ", " . V_FromSeq . ", " . V_FromStep . ", " . V_ToSeq . ", " . V_ToStep . ", " . V_Over . ", " . V_Quantity . ", " . V_AutoOver . ", " . V_CheckComp . ") using MF_WaitForImage2 (Focus_MoveTransType, Focus_MoveTransError, 0) failed."
MF_ErrorLog(ErrorMsg, false)
return 0
}
If (V_Result = 2)
{
ErrorMsg := "F_CheckLog (" . V_JobNum . ", " . V_Type . ", " . V_FromSeq . ", " . V_FromStep . ", " . V_ToSeq . ", " . V_ToStep . ", " . V_Over . ", " . V_Quantity . ", " . V_AutoOver . ", " . V_CheckComp . ") could not continue as the Job Number does not exist."
MF_ErrorLog(ErrorMsg, false)
send {delete}
return 2
}
If (V_CheckComp = true)
{
send {tab}^l
V_Result := MF_WaitForImage(Focus_MoveTransOperations, 0)
If (V_Result = 0)
{
ErrorMsg := "F_CheckLog (" . V_JobNum . ", " . V_Type . ", " . V_FromSeq . ", " . V_FromStep . ", " . V_ToSeq . ", " . V_ToStep . ", " . V_Over . ", " . V_Quantity . ", " . V_AutoOver . ", " . V_CheckComp . ") using MF_WaitForImage (Focus_MoveTransOperations, 0) failed."
MF_ErrorLog(ErrorMsg, false)
return 0
}
send ^{end}{enter}
V_Result := MF_WaitForImage(Focus_MoveTrans, 0)
If (V_Result = 0)
{
ErrorMsg := "F_CheckLog (" . V_JobNum . ", " . V_Type . ", " . V_FromSeq . ", " . V_FromStep . ", " . V_ToSeq . ", " . V_ToStep . ", " . V_Over . ", " . V_Quantity . ", " . V_AutoOver . ", " . V_CheckComp . ") using MF_WaitForImage (Focus_MoveTrans, 0) failed."
MF_ErrorLog(ErrorMsg, false)
return 0
}
send +{tab}
V_Result := MF_Copy(V_FinalStep)
If (V_Result = 0)
{
ErrorMsg := "F_CheckLog (" . V_JobNum . ", " . V_Type . ", " . V_FromSeq . ", " . V_FromStep . ", " . V_ToSeq . ", " . V_ToStep . ", " . V_Over . ", " . V_Quantity . ", " . V_AutoOver . ", " . V_CheckComp . ") using MF_Copy (V_FinalStep) failed."
MF_ErrorLog(ErrorMsg, false)
return 0
}
send {f6}
V_Result := MF_WaitForImage(Focus_MoveTransClear, 0)
If (V_Result = 0)
{
ErrorMsg := "F_CheckLog (" . V_JobNum . ", " . V_Type . ", " . V_FromSeq . ", " . V_FromStep . ", " . V_ToSeq . ", " . V_ToStep . ", " . V_Over . ", " . V_Quantity . ", " . V_AutoOver . ", " . V_CheckComp . ") using MF_WaitForImage (Focus_MoveTransClear, 0) failed."
MF_ErrorLog(ErrorMsg, false)
return 0
}
send %V_JobNum%{tab}
V_Result := MF_WaitForImage(Focus_MoveTransType, 0)
If (V_Result = 0)
{
ErrorMsg := "F_CheckLog (" . V_JobNum . ", " . V_Type . ", " . V_FromSeq . ", " . V_FromStep . ", " . V_ToSeq . ", " . V_ToStep . ", " . V_Over . ", " . V_Quantity . ", " . V_AutoOver . ", " . V_CheckComp . ") using MF_WaitForImage (Focus_MoveTransType, 0) failed."
MF_ErrorLog(ErrorMsg, false)
return 0
}
If (V_Type = 1) and (V_FromSeq = V_FinalStep)
V_Type = 2
}
If (V_Type = 1)
send !m{tab}%V_FromSeq%{tab}%V_FromStep%{tab}%V_ToSeq%{tab}%V_ToStep%{tab}
Else If (V_Type = 2)
send !c{tab}%V_FromSeq%{tab}%V_FromStep%{tab}
Else If (V_Type = 3)
send !u{tab}%V_ToSeq%{tab}%V_ToStep%
If (V_Over = true)
send {space}
send {tab 2}%V_Quantity%{enter}
V_Result := MF_WaitForImage2(Focus_MoveTransClear, Focus_MoveTransError2, 0)
If (V_Result = 0)
{
ErrorMsg := "F_CheckLog (" . V_JobNum . ", " . V_Type . ", " . V_FromSeq . ", " . V_FromStep . ", " . V_ToSeq . ", " . V_ToStep . ", " . V_Over . ", " . V_Quantity . ", " . V_AutoOver . ", " . V_CheckComp . ") using MF_WaitForImage2 (Focus_MoveTransClear, Focus_MoveTransError2, 0) failed."
MF_ErrorLog(ErrorMsg, false)
return 0
}
If (V_Result = 2)
{
If (V_AutoOver = true)
send {enter}{delete}+{tab 2}{space}{tab 2}%V_Quantity%{enter}
Else
{
send {enter}{f6}
ErrorMsg := "F_CheckLog (" . V_JobNum . ", " . V_Type . ", " . V_FromSeq . ", " . V_FromStep . ", " . V_ToSeq . ", " . V_ToStep . ", " . V_Over . ", " . V_Quantity . ", " . V_AutoOver . ", " . V_CheckComp . ") could not log job because the Quantity was greater than the Available and Overcomplete was not on."
MF_ErrorLog(ErrorMsg, false)
return 3
}
}
return 1
}
;;;;;;;;;;
;GUI
;;;;;;;;;;
IniRead, V_FromSeq, %IniFile%, Defaults, FromSeq, 20
Gui, Add, Text,, Enter the Job Number:
Gui, Add, Edit, vV_JobNum
Gui, Add, Text,, Enter the Quantity:
Gui, Add, Edit, vV_Quantity
Gui, Add, Text,, Enter your Scrap:
Gui, Add, Edit, vV_Scrap
Gui, Add, Button, gSub_LogJob Default, &Log The Job
Gui, Add, Text,, Starting Sequence:
Gui, Add, Edit, vV_FromSeq, %V_FromSeq%
;;;;;;;;;;;;;;;
;Auto-Execute
;;;;;;;;;;;;;;;
MF_ErrorClear()
;;;;;;;;;;
;Keys
;;;;;;;;;;
^+r::
reload
return
^+e::
edit
return
^+1::
GoSub, Sub_ShowLogScreen
return
;;;;;;;;;;;;;;;
;Subroutines
;;;;;;;;;;;;;;;
Sub_ShowLogScreen:
Gui, Show
return
Sub_LogJob:
Gui, Submit
V_Result := F_CheckLog(V_JobNum, 1, V_FromSeq, "Q", V_FromSeq+10, "Q", false, V_Quantity, false, true)
If (V_Result = 0)
{
ErrorMsg := "Could not log the job using F_CheckLog(V_JobNum, 1, V_FromSeq, ""Q"", V_FromSeq+10, ""Q"", false, V_Quantity, false, true). See Error Log for details."
MF_ErrorLog(ErrorMsg, true)
}
If (V_Result = 2)
{
ErrorMsg := "Could not log the job using F_CheckLog(V_JobNum, 1, V_FromSeq, ""Q"", V_FromSeq+10, ""Q"", false, V_Quantity, false, true). Job Number invalid. See Error Log for details."
MF_ErrorLog(ErrorMsg, true)
}
If (V_Result = 3)
{
ErrorMsg := "Could not log the job using F_CheckLog(V_JobNum, 1, V_FromSeq, ""Q"", V_FromSeq+10, ""Q"", false, V_Quantity, false, true). Quantity invalid. See Error Log for details."
MF_ErrorLog(ErrorMsg, true)
}
V_Result := F_CheckLog(V_JobNum, 1, V_FromSeq, "Q", V_FromSeq, "S", false, V_Scrap, false, false)
If (V_Result = 0)
{
ErrorMsg := "Could not log the job using F_CheckLog(V_JobNum, 1, V_FromSeq, ""Q"", V_FromSeq, ""S"", false, V_Quantity, false, false). See Error Log for details."
MF_ErrorLog(ErrorMsg, true)
}
If (V_Result = 2)
{
ErrorMsg := "Could not log the job using F_CheckLog(V_JobNum, 1, V_FromSeq, ""Q"", V_FromSeq, ""S"", false, V_Quantity, false, false). Job Number invalid. See Error Log for details."
MF_ErrorLog(ErrorMsg, true)
}
If (V_Result = 3)
{
ErrorMsg := "Could not log the job using F_CheckLog(V_JobNum, 1, V_FromSeq, ""Q"", V_FromSeq, ""S"", false, V_Quantity, false, false). Quantity invalid. See Error Log for details."
MF_ErrorLog(ErrorMsg, true)
}
MsgBox Job Successfully Logged.
return
ExitSub:
IniWrite, %V_FromSeq%, %IniFile%, Defaults, FromSeq
ExitApp
return