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

StackOverflow https://stackoverflow.com/questions/8844279

  •  27-10-2019
  •  | 
  •  

Question

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.

Was it helpful?

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.

OTHER TIPS

The type of window handles is string. The reason for that is WinList returns both the window handle and the window title. A title cannot be fit into a handle type, but a handle can be fit into a string type (for title). My guess is that they took that design descision and applied it to other functions as well. If you look at the documentation for WinGetHandle it will tell you the return type for a handle: It's a string.

AutoIt has a function that can "convert" a base 16 number into an HWND object.

Exactly! That's the key. AutoIt does this for you. You're trying to convert the handle into something useful for AutoIt, but AutoIt can already use those handles stored as strings.

Your test should be:

In: autoIt = win32com.client.Dispatch("AutoItX3.Control")
In: mainWindowTitle = "Untitled"
In: mainWindowHandle = autoIt.WinGetHandle(mainWindowTitle)
In: mainWindowHandle
Out: u'000204AC'
In: autoIt.WinGetTitle(mainWindowHandle)
Out: u'Untitled - Notepad'

When you want to use that handle in other libraries, you may run into some problems. I would recommend then that you try to parse the number like you did in your tests, and pass it along. AutoIt is 'smart' enough to figure out what to do in most cases, maybe the library isn't though.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top