Python – Getting Python and AutoIT to work together using win32com: what’s up with those window handles

autoitpythonpywin32

I have a program with a GUI interface whose initial set-up I need to do manually. AutoIt has been superbly helpful for that so far, as it provides very easy ways to work even with complex-to-access GUI objects (drop down lists, appear-on-hover menus, etc.).

However, the script that I'll eventually be needing in order to do the program setup will need to be passed a large array/list of variables – there are a lot of different settings that need to be changed.

I've set up the logic for deciding what these set-up variables will be using a Python script. Now I'm trying to figure out how to get Python and AutoIt to talk to each other.

Calling a custom AutoIt script from the command line using Python is mostly out of the question because of the large number of variables that would need to be passed. Doesn't feel pretty. I could try and have Python write an AutoIt "key file", which AutoIt could then read in order to set its initial variables, but I'd like to make sure I've exhausted all options for Python to work directly with AutoIt first.

To that end, I've been trying to use Python along with the win32com library to interface with AutoIt. Things seem to be working well – as long as I reference windows/menus/objects by their string titles rather than their (memory?) handles. This is problematic, as my set-up scripts might be running in parallel, setting up two or more separate files at the same time. If this is the case, opening up a box with a title string "Open file…" in each file at the same time might confuse things.

The obvious way to get around this in AutoIt is to work with the "handles" of the objects in question, which I believe are memory addresses of some kind, rather than their string titles. I'm guessing these are memory addresses as the AutoIt Window Info tool, when pointed to a particular Window/GUI object option lists a hexadecimal number as the object's handle value.

AutoIt has a suite of functions that get the handles of windows, menus, etc. They are implemented in the AutoIt COM dll, but I've not been able to get them to work in Python. The handle functions return a unicode object in Python, not a hex string as in AutoIt. I think this is the reason why functions which then try to use this "handle" in Python don't work.

Example:

autoIt = win32com.client.Dispatch("AutoItX3.Control")
windowHandle = autoIt.WinGetHandle(knownWindowTitle)
returnedWindowTitle = autoIt.WinGetTitle(windowHandle)

Usually, returnedWindowTitle and knownWindowTitle do not match as returnedWindowTitle always seems to be "0". hat's happening here?

Are there other ways for me to call custom AutoIt functions apart from using win32com, the command line, or using an AutoIt keyfile?

Thanks for your help.

EDIT: I forgot to mention that the unicode strings do in fact match the hexadecimal numbers that I get when I print out the handle variable in AutoIt.

For example, in Python, the handle variable when printed out gives me u'000C0326'. In AutoIt it gives me '0x000C0326'.

EDIT: Some trials based on Mat's suggestions:

In: autoIt = win32com.client.Dispatch("AutoItX3.Control")
In: mainWindowTitle = "Untitled"
In: mainWindowHandle = autoIt.WinGetHandle(mainWindowTitle)
In: mainWindowHandle
Out: u'000204AC'
In: testHandle = int(mainWindowHandle, 16)
In: testHandle
Out: 132268
In: autoIt.WinGetTitle(testHandle)
Out: u'0'

EDIT: I found out the type of the window handle object: it's a Microsoft HWND object. AutoIt has a function that can "convert" a base 16 number into an HWND object (i.e. find the HWND object with that base 16 number memory/handle/etc.). Just my luck that they didn't put that function into AutoItX (the COM dll). So, if I really want to run with this, I'll have to try and figure out how to return whatever object it is that's pointed to by the base 16 address, and then transfer it the right way to AutoItX? I'm probably sounding very confused, because all of this is not super clear in my head right now.

Best Solution

For the sake of search, I'll post the solution that I've found.

Here's the code:

In: autoIt = win32com.client.Dispatch("AutoItX3.Control")
In: autoIt.AutoItSetOption("WinTitleMatchMode", 4)
In: mainWindowTitle = "Untitled"
In: mainWindowHandle = autoIt.WinGetHandle(mainWindowTitle)
In: mainWindowHandle
Out: u'000204AC'
In: testHandle = "[HANDLE:%s]" % mainWindowHandle
In: autoIt.WinGetTitle(testHandle)
Out: u'Untitled - Notepad'

autoIt.AutoItSetOption("WinTitleMatchMode", 4) tells autoit to use advanced title matching, which allows us to specify a window handle with the [HANDLE:000204AC] string.

No need for the actual window handle here.

By the way, I discovered this solution by stumbling on this forum post. I've found that it's often helpful to not restrict my searches to the specific language I'm looking for. Most of the time, a solution can be found in a different language which can be easily ported to the language of your choice.