Autoit and notepad - automation

I have an application, wherein I get a "Save As" dialog-box. At times, if a file exists with the same name, then another dialog box comes in, with the same name "Save As". The following is the code, which I wrote but it doesn't work as expected.
Global $sTitle = "Save As"
WinWait($sTitle)
WinWaitActive($sTitle)
ControlClick($sTitle, "Save", "[CLASS:Button; TEXT:&Save; INSTANCE:2]")
ControlSetText($sTitle, "", "CLASS:Button; INSTANCE:2]", $file_name)
SendKeepActive($sTitle)
Send("{ENTER}")
Sleep(4000)
WinWaitActive($sTitle,"",3)
If WinExists($sTitle, "No") Then Send("{ENTER}")
If WinExists("Exit OmniPeek") Then
Send("{ENTER}")
Else
Sleep(2000)
WinClose($closing_file)
EndIf
The idea is to check if the second "Save As" dialog box comes and if does come in, then over-write the existing file. This however, doesn't seem to be working with the autoit script that I wrote.
Can someone help me with this script? You can re-create the issue by using Notepad as well. Just have a file with a name abc.txt and try to save a file with the same name
You will get another dialog box with the name "Save As".

Try this:
Example()
Func Example()
; Run Notepad
Run("notepad.exe")
; Wait 10 seconds for the Notepad window to appear.
Local $hWnd = WinWait("[CLASS:Notepad]", "", 10)
; Keep the Notepad window active when using the Send function.
SendKeepActive("[CLASS:Notepad]")
; Simulate entering a string of text. If you try to change to a different window other than Notepad, then the Notepad window will
; be brought to focus again.
For $i = 1 To 10
Sleep(5)
Send("notepad - ")
Next
; Disable the Notepad window being active when using the Send function.
SendKeepActive("")
; Close the Notepad window using the handle returned by WinWait.
WinClose($hWnd)
Send("{ENTER}") ; <<< SAVE
; Now a screen will pop up and ask to save the changes, the classname of the window is called
; "#32770" and simulating the "TAB" key to move to the second button in which the "ENTER" is simulated to not "save the file"
WinWaitActive("[CLASS:#32770]", '', 2)
Sleep(50)
Send('newName.txt')
Sleep(1000)
Send("{TAB}{ENTER}")
EndFunc ;==>Example

Related

Make custom file open by a custom program VB

How to make a file (.jkl extension for example) that when you open it, your custom program will pop-up.
For example:
I have a test.jkl file
If i double-click it, my program will be the one to read it.
Just like a .jpg file extension, when double-clicking the file, paint will pop-up and shows the image.
My code when changing the file ext is just simple
File.Copy(origFile, origFile.Replace("txt", "jkl")
File.Delete(origFile)
So now i have a .jkl file, now what I need to do is when the user double clicks the .jkl file, this program will automatically open, ask where to save it, and change it back to .txt to the path where the user wants to.
How can I do this?
Put it the form load event. it will write again and again. It won't destroy your PC. If you want to more carefully. Read registry check if it is exist then skip write again.
Code:
My.Computer.Registry.ClassesRoot.CreateSubKey(".jkl").SetValue_
("", "jkl", Microsoft.Win32.RegistryValueKind.String)
My.Computer.Registry.ClassesRoot.CreateSubKey_
("jkl\shell\open\command").SetValue("", Application.ExecutablePath & _
" ""%l"" ", Microsoft.Win32.RegistryValueKind.String)
link for demo project: http://www.codeproject.com/Articles/18594/File-Association-in-VB-NET
I don't think code is required. Once the file is saved as .jkl, right click the file and select the option "open with" -> "Choose default program" -> then browse to the exe you have written to save the file as .txt file.
If open with option is not available double click the file and select the option to select default program. Now browse to your exe.
The command line parameter args[0] is the file full name.
I have tried with C# code same can be done with VB code.
static void Main(string[] args)
{
Console.WriteLine("0: " + args[0]);
//Code to rename the file
Console.WriteLine("Done. Press enter");
Console.ReadKey();
}
VB Code using online converter
Private Shared Sub Main(args As String())
Console.WriteLine("0: " + args(0))
'Code to rename the file
Console.WriteLine("Done. Press enter")
Console.ReadKey()
End Sub

Wait for hotkey?

I'm wondering why my script doesn't wait for me to send the hotkey Alt + Shift + q?
WinWaitActive("Open")
HotKeySet("+!q", "ClickFill")
Func ClickFill()
ControlClick("Open", "", "[CLASS:32770]")
ControlSend("Open", "", "[CLASS:32770]", "C:\au3")
Exit
The script just exits after the 'Open' dialog becomes active. I'm trying to get the script to click on class 32770, which is the address bar, then send the au3 directory to it, which is my autoit scripts directory. My hope is that the script will always stay open, so any time I try to open something, it works.
Second attempt
WinWaitActive("Open")
HotKeySet("+!q", "ClickFill")
While(1)
Sleep(1000)
WEnd
Func ClickFill()
ControlClick("Open", "", "[CLASS:32770]")
ControlSend("Open", "", "[CLASS:32770]", "C:\au3")
Exit
The script remains open, but the hotkey is not effective.
It looks like you just need to close your function with a "EndFunc". This works for me.
WinWaitActive("Open")
HotKeySet("+!q", "ClickFill")
While(1)
Sleep(1000)
WEnd
Func ClickFill()
MsgBox(262144,"","Look I work!")
ControlClick("Open", "", "[CLASS:32770]")
ControlSend("Open", "", "[CLASS:32770]", "C:\au3")
Exit
EndFunc
Here is some working code for Notepad++
Global $g_hWinHandle, $g_hOpenWin
;set hotkey
HotKeySet("+!q", "ClickFill")
;open notepad++
ShellExecute(#ProgramFilesDir & "\notepad++\notepad++.exe")
;wait for notepad++ window
WinWait("[Class:Notepad++]")
If #error Then Exit
;get notepad++ window handle
$g_hWinHandle = WinGetHandle("[Class:Notepad++]")
;make sure the window is active
WinActivate($g_hWinHandle)
WinWaitActive($g_hWinHandle)
;open "Open" dialog
WinMenuSelectItem($g_hWinHandle, "", "&File", "&Open...")
;wait for "Open" dialog window
WinWaitActive("Open")
;get the "Open" dialog window handle
$g_hOpenWin = WinGetHandle("Open")
If #error Then Exit
;wait for hotkey
While (1)
Sleep(1000)
WEnd
Func ClickFill()
;make sure the window is active
WinActivate($g_hOpenWin)
WinWaitActive($g_hOpenWin)
;focus the toolbar
ControlFocus($g_hOpenWin, "", "[CLASS:ToolbarWindow32; INSTANCE:3]")
ControlCommand($g_hOpenWin, "", "[CLASS:ToolbarWindow32; INSTANCE:3]", "SendCommandID", "1280")
;send our command to the toolbar
ControlSetText($g_hOpenWin, "", "Edit2", "C:\au3")
ControlSend($g_hOpenWin, "", "Edit2", "{ENTER}")
Exit
EndFunc ;==>ClickFill
In the above example you will see that I use ControlFocus and ControlCommand on the ToolbarWindow32 control. Most dialog windows have a ToolbarWindow32 control. To simulate clicking on them you have to use ControlCommand with the SendCommandID option. You can get that ID under the toolbar tab in the AutoIt info tool. However, you will see that once the ToolbarWindow32 control is clicked on it gives focus to an edit control. That edit control is what you need to send text to if you want to change directories. Finding that edit control with the AutoIt tool can be a bit tricky. You will have to make sure "Freeze" is unchecked under options.
If you are still having problems with the code I would recommend that you first make sure you can get the code working without a hotkey. Then try it with a one letter hotkey and then lastly try it with your multiple hotkey combination. With out having access to your computer I am just guessing but I suspect that you are not accessing the address bar right. There might also be a program running on your computer that is using the same hotkey.

Three AutoIT script causing issue

All,
I have Selenium script which attach documents to Transaction. I am using AutoIT. Now, the problem I am facing is: I have to attach 3 documents (one by one). My steps are: I execute AutoIT script. Then script click on Browse 1 - button in my transaction screen - File Upload pop up appears. My Address of file is pasted correctly in text area as well.
But when AutoIT script click on Open button - another File Upload window appears.
I did added some wait in my script before clicking on Browser 2 button. But somehow I am missing something which is causing this problem.
Another thing is that: Same script works sometimes. Failure is more than success.
WinExists ("TITLE")
While 1
Select
case WinExists("File Upload")
WinActivate("File Upload")
Sleep(5000)
Local $sTestPath = _PathFull(#ScriptDir & "\ABC.jpg")
ControlClick("File Upload", "", "Edit")
Send($sTestPath)
Sleep(5000)
Send("{ENTER}")
Sleep(5000)
Exit
Case WinExists("Choose File to Upload")
WinActivate("Choose File to Upload")
Sleep(5000)
Local $sTestPath = _PathFull(#ScriptDir & "\ABC.jpg")
ControlClick("File Upload", "", "Edit")
Send($sTestPath)
Sleep(5000)
Send("{ENTER}")
Sleep(5000)
Exit
Case WinExists("Open")
WinActivate("Choose File to Upload")
Sleep(5000)
Local $sTestPath = _PathFull(#ScriptDir & "\ABC.jpg")
ControlClick("File Upload", "", "Edit")
Send($sTestPath)
Sleep(5000)
Send("{ENTER}")
Sleep(5000)
Exit
EndSelect
WEnd
Don't use send.
Send ( "keys" [, flag] ) - Sends simulated keystrokes to the active
window.
Better way:
ControlSend () can send characters to targeted window (can be inactive).
Most reliable way:
ControlSetText () - Sets text of a control.
Play with AutoitWindowInfo tool and tweak the script below if needed.
#RequireAdmin ;Will give your script a permission elevation (sometimes its needed)
Opt("WinTitleMatchMode", 1) ;1=start, 2=subStr, 3=exact, 4=advanced, -1 to -4=Nocase
Opt("WinSearchChildren", 1) ;0=no, 1=search children also
WinActivate("File Upload")
WinWaitActive("File Upload","",10)
ControlFocus("File Upload","","Edit1")
ControlSetText("File Upload","","Edit1","dropdowns.jpg")
ControlSend("File Upload", "", "Edit1", "{ENTER}")

Can't use a title's Class to automate Windows file upload using AutoIt

I am trying to use AutoIt for Windows file upload. I am clicking a browse button which will open file upload popup. I want AutoIt to type the location of the file and click open.
I need to use FF, Chrome, and IE for testing. I am able to get this to work if I use the Title, but the problem is that each browser has a different title. I would like to use class, as it is #32700 for all browsers. I've tried using class instead of the title, but its not working.
When I use title, everything works fine. Below is an example for Firefox. In this script, the file name is entered and open is clicked.
ControlFocus("File Upload","","Edit1")
ControlSetText("File Upload", "", "Edit1", "SomeFile.txt")
ControlClick("File Upload", "","Button1");
When I try to use class, text is not being entered and the open button is not getting clicked. There are no errors in the AutoIt script editor, so I'm not sure why this isn't working.
ControlFocus("[CLASS:#32770]","","Edit1")
ControlSetText("[CLASS:#32770]", "", "Edit1", "SomeFile.txt")
ControlClick("[CLASS:#32770]", "","Button1");
I've also tried to add all three browser titles to 1 AutoIt script. The below script is working for Firefox and IE, but doesn't do anything in Chrome.
Local $OrgFile = "SomeFile.csv"
Local $ControlIDText = "Edit1"
Local $ControlIDButton = "Button1"
Local $Title_FF = "File Upload"
Local $Title_Chrome = "Open"
Local $Title_IE = "Choose File to Upload"
;Firefox Import
ControlFocus($Title_FF,"",$ControlIDText)
ControlSetText($Title_FF, "", $ControlIDText, $OrgFile)
ControlClick($Title_FF, "",$ControlIDButton);
;Chrome Import
ControlFocus($Title_Chrome,"",$ControlIDText)
ControlSetText($Title_Chrome, "", $ControlIDText, $OrgFile)
ControlClick($Title_Chrome, "",$ControlIDButton);
;IE Import
ControlFocus($Title_IE,"",$ControlIDText)
ControlSetText($Title_IE, "", $ControlIDText, $OrgFile)
ControlClick($Title_IE, "",$ControlIDButton);
You need to set WinTitleMatchMode option to 4 if you want to use advanced title matching (eg. CLASS).
#RequireAdmin ;Will give your script a permission elevation (sometimes its needed)
Opt("WinTitleMatchMode", 4) ;1=start, 2=subStr, 3=exact, 4=advanced, -1 to -4=Nocase
Opt("WinSearchChildren", 1) ;0=no, 1=search children also
ControlFocus("[CLASS:#32770]","","Edit1")
ControlSetText("[CLASS:#32770]", "", "Edit1", "SomeFile.txt")
ControlClick("[CLASS:#32770]", "","Button1");

AutoHotkey - Perform action based on clicked menu item

I looked around the AHK forums, google, and here on stack overflow and could not find any method for pulling this off, so thanks BIG TIME in advance if you can figure this one out. I am using notepad in my examples, but I'm writing this script for a complicated Point Of Sale program.
I want to do something almost exactly like this, but using the application menus as described below instead of a button.
I would like to have a script that performs an action if a certain menu item is clicked. It does not matter whether that is determined by menu position, label or otherwise. Cursor position, however, is probably not viable for my needs.
A simple example of this would be to open a MsgBox when File-Open is selected with the mouse in notepad.
I have implemented a few techniques that enabled me to pull variables out of most control objects following a left click (buttons, drop-down menus, etc), but when I use the application menu (for example, in notepad: file-save or file-open) It returns a blank string. For example:
#z::
MouseGetPos,,,,Ctrl,2
ControlGetText, Text,,ahk_id %Ctrl%
MouseClick, left
Sleep 2500
MsgBox, %Text%
(Note that I used windows-z so as to not return a MsgBox after every left-click.)
Will return 'cancel' if the cancel button was pressed in the 'file-save as' dialogue of notepad, but returns nothing if I activate it while selecting anything from the application menus (file, edit, format, etc.)
I know that these menus are accessible to AHK, as you can do the following do activate 'File-Save' from the notepad menu:
WinMenuSelectItem, Untitled - Notepad,File,Save
But when I use window spy, I see the objects behind the menu, rather than strings that are actually in the menu.
Are these menus actually separate windows that I need to switch to active to read? Or am I trying to do something impossible?
Big thanks in advance, this is something that's been driving me crazy!
Menus are not that easy to get info from, at least not with autohotkeys built-in commands, you will need to use DllCall's to get the info you need.
I have made you an example that works with notepad for me on win7 64b
What i did in the example is look for notepad run it if its not there then get the ID (hWnd) of the notepad window
When you press ctrl + LButton a DllCall to GetMenu using the ID of the notepad window is used to get a menu handle.
After that more DllCall's are used to get things like GetMenuItemCount, GetSubMenu and GetMenuItemInfo.
What this does is it lets us loop over the menu items one by one and getting info about them, in this example we're getting the state of the items, specifically the highlight state.
When an item is found that has the highlight state the script stores the indexs of the item and breaks the loops.
As this is only an example all it does is display a string message with the index numbers and sends a LButton press
Example:
ifWinNotExist, ahk_class Notepad
{
Run, notepad.exe
WinWait, ahk_class Notepad
}
WinGet, hWnd, ID,
^Lbutton::
hMenu :=DllCall("GetMenu", "Uint", hWnd)
loop % (count := DllCall("GetMenuItemCount", "ptr", hMenu))
{
menu_index := A_index
; Note that menu item positions are zero-based.
hSubMenu := DllCall("GetSubMenu", "Uint", hMenu, "int", (A_index-1))
; Set the capacity of mii to sizeof(MENUITEMINFO)
VarSetCapacity(mii, A_PtrSize=8 ? (Size:=80) : (Size:=48), 0)
; Set the cbSize field to sizeof(MENUITEMINFO)
NumPut(Size, mii, 0)
; Set the mask to whatever you want to retrieve.
; In this case I set it to MIIM_STATE=1.
NumPut(1, mii, 4)
loop % (subCount := DllCall("GetMenuItemCount", "ptr", hSubMenu))
{
Sub_index := A_index
; Note that menu item positions are zero-based.
DllCall("GetMenuItemInfo", "UInt", hSubMenu, "UInt", (A_index-1), "UInt", 1, "UInt", &mii)
; Get the state field out of the struct.
fState := NumGet(mii, 12)
if (fState & 0x80) ; 0x80 MFS_HILITE | 0x8 MFS_CHECKED
{
MenuString := "Found in top #" menu_index " Sub pos #" Sub_index
break 2
}
}
}
if (MenuString)
{
Tooltip % MenuString
}
else
{
tooltip no menu item highlighted
}
send {Lbutton}
return
I hope that helps you get an idea of what is needed to do what your trying to do, other possible DllCalls to Look at are MenuItemFromPoint, GetMenuString.
This can take time to get right, but with the Dllcalls i have shown in this example, I hope that you can find other examples of how to use them with autohotkey on the forums.
This AutoHotkey script should do what you require.
It has been tested on Notepad (Windows 7), and should be readily adaptable to other programs that use the standard context menus still used in the vast majority of software. Although many programs use custom menu bars, the context menus are often still standard context menus.
I have provided two scripts, one will show a ToolTip and block triggering a menu item, whenever any menu item is pressed, which is useful for understanding and for diagnostic purposes.
The second script will show a ToolTip and block triggering any menu item if its text string starts with 'Open'.
Note: the text of the Notepad menu item is
Open... Ctrl+O (Open...[tab]Ctrl+O) and not simply 'Open'.
-
;==================================================
;tested on Notepad (Windows 7)
;block any clicks on any menu items when notepad is the active window
;note: to bypass this and click an item anyway, use ctrl+click
;note: requires Acc.ahk library in AutoHotkey\Lib folder
;https://github.com/Drugoy/Autohotkey-scripts-.ahk/blob/master/Libraries/Acc.ahk
;on right of screen right-click Raw, Save target as...
#IfWinActive, ahk_class Notepad
;LButton::
CoordMode, Mouse, Screen
MouseGetPos, , , hWnd
WinGetClass, vWinClass, ahk_id %hWnd%
if vWinClass in #32768
{
vCount++ ;your code here
ToolTip blocked %vCount%, 500, 200 ;your code here
Return
}
SendInput {LButton Down}
KeyWait, LButton
MouseGetPos, vPosX, vPosY, hWnd
WinGetClass, vWinClass, ahk_id %hWnd%
if vWinClass in #32768
{
ControlSend, Dummy, {Click, 0, 0}, ahk_class Notepad
vCount++ ;your code here
ToolTip blocked %vCount%, 500, 200 ;your code here
Return
}
SendInput {LButton Up}
Return
#IfWinActive
;==================================================
;tested on Notepad (Windows 7)
;block any clicks on the 'open' menu item when notepad is the active window
;note: to bypass this and click an item anyway, use ctrl+click
;note: requires Acc.ahk library in AutoHotkey\Lib folder
;https://github.com/Drugoy/Autohotkey-scripts-.ahk/blob/master/Libraries/Acc.ahk
;on right of screen right-click Raw, Save target as...
#IfWinActive, ahk_class Notepad
LButton::
CoordMode, Mouse, Screen
MouseGetPos, , , hWnd
WinGetClass, vWinClass, ahk_id %hWnd%
if vWinClass in #32768
{
vItemText := ""
oAcc := Acc_Get("Object", "1", 0, "ahk_id " hWnd)
Loop, % oAcc.accChildCount
if (oAcc.accState(A_Index) & 0x80) ;MF_HILITE := 0x80
if (1, vItemText := oAcc.accName(A_Index))
break
if (SubStr(vItemText, 1, 4) = "Open")
{
vCount++ ;your code here
ToolTip blocked %vCount%, 500, 200 ;your code here
Return
}
}
SendInput {LButton Down}
KeyWait, LButton
MouseGetPos, vPosX, vPosY, hWnd
WinGetClass, vWinClass, ahk_id %hWnd%
if vWinClass in #32768
{
ControlSend, Dummy, {Click, 0, 0}, ahk_class Notepad
vItemText := ""
oAcc := Acc_Get("Object", "1", 0, "ahk_id " hWnd)
Loop, % oAcc.accChildCount
if (oAcc.accState(A_Index) & 0x80) ;MF_HILITE := 0x80
if (1, vItemText := oAcc.accName(A_Index))
break
if (SubStr(vItemText, 1, 4) = "Open")
{
vCount++ ;your code here
ToolTip blocked %vCount%, 500, 200 ;your code here
Return
}
}
SendInput {LButton Up}
Return
#IfWinActive
;==================================================
Note:
The code samples posted in the two links below, achieve related goals.
Is it possible to catch the close button and minimize the window instead? AutoHotKey
AutoHotKey: Run code on Window Event (Close)
Note:
The function JEE_MenuIsActive, link below, can be used to check whether
the menu bar/sysmenu bar is active
in order to distinguish title bar menus from right-click context menus.
GUI COMMANDS: COMPLETE RETHINK - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=5&t=25893