使用win32com让Python和AutoIT一起工作:这些窗口句柄有什么用?

时间:2012-01-13 00:15:58

标签: python autoit pywin32

我有一个带有GUI界面的程序,我需要手动进行初始设置。到目前为止,AutoIt对此非常有帮助,因为它提供了非常简单的工作方式,即使是复杂的访问GUI对象(下拉列表,悬停菜单等)。

但是,为了进行程序设置,我最终需要的脚本需要传递一个大型数组/变量列表 - 有一个需要不同设置的 lot 要改变。

我已经设置了逻辑,用于确定这些设置变量将使用Python脚本。现在我想弄清楚如何让Python和AutoIt相互通信。

使用Python从命令行调用自定义AutoIt脚本大多是不可能的,因为需要传递大量变量。不舒服。我可以尝试让Python编写一个AutoIt“密钥文件”,然后AutoIt可以读取它以设置其初始变量,但我想确保我已经用尽所有Python的选项,以便首先直接使用AutoIt。

为此,我一直在尝试使用Python和win32com库来与AutoIt进行交互。事情似乎运作良好 - 只要我通过字符串标题而不是它们的(内存?)句柄来引用窗口/菜单/对象。这是有问题的,因为我的设置脚本可能并行运行,同时设置两个或多个单独的文件。如果是这种情况,在每个文件中同时打开一个带有标题字符串“打开文件...”的框可能会让事情变得混乱。

在AutoIt中解决这个问题的显而易见的方法是使用相关对象的“句柄”,我相信这些是某种内存地址,而不是字符串标题。我猜这些是内存地址作为AutoIt窗口信息工具,当指向特定的窗口/ GUI对象选项时,会将十六进制数字列为对象的句柄值。

AutoIt有一套函数可以获取窗口,菜单等的句柄。它们是在AutoIt COM dll中实现的,但是我无法让它们在Python中工作。 handle函数返回Python中的unicode对象,而不是AutoIt中的十六进制字符串。我认为这就是为什么然后尝试在Python中使用这个“句柄”的函数不起作用的原因。

示例:

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

通常,returnsWindowTitle和knownWindowTitle不匹配,因为returnsWindowTitle似乎总是“0”。帽子发生在这里?

除了使用win32com,命令行或使用AutoIt密钥文件外,还有其他方法可以调用自定义AutoIt函数吗?

感谢您的帮助。

编辑:我忘了提到unicode字符串实际上与我在AutoIt中打印出handle变量时得到的十六进制数相匹配。

例如,在Python中,打印出来的句柄变量给出了u'000C0326'。在AutoIt中它给我'0x000C0326'。

编辑:根据Mat的建议进行了一些试验:

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'

编辑:我发现了窗口句柄对象的类型:它是一个Microsoft HWND对象。 AutoIt具有可以将基数16“转换”为HWND对象的功能(即,找到具有该基数16数字存储器/句柄/等的HWND对象)。只是我的运气,他们没有将该功能放入AutoItX(COM dll)。所以,如果我真的想用这个运行,我将不得不试图弄清楚如何返回基本16地址所指向的任何对象,然后以正确的方式将其传递给AutoItX?我可能听起来很困惑,因为现在所有这一切都不是很清楚。

2 个答案:

答案 0 :(得分:2)

窗口句柄的类型是字符串。原因是WinList返回窗口句柄和窗口标题。标题不能适合句柄类型,但句柄可以适合字符串类型(标题)。我的猜测是他们采取了这种设计策略并将其应用于其他功能。如果你查看WinGetHandle的文档,它会告诉你句柄的返回类型:它是一个字符串。

  

AutoIt具有可以将基数16转换为HWND对象的功能。

完全!这是关键。 AutoIt为您完成此操作。您正在尝试将句柄转换为对AutoIt有用的东西,但AutoIt已经可以使用存储为字符串的句柄。

您的测试应该是:

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'

如果要在其他库中使用该句柄,可能会遇到一些问题。我建议你尝试解析你在测试中所做的数字,然后传递它。 AutoIt“聪明”足以弄清楚在大多数情况下该做什么,也许库不是。

答案 1 :(得分:2)

为了搜索,我会发布我找到的解决方案。

以下是代码:

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)告诉autoit使用高级标题匹配,这允许我们使用[HANDLE:000204AC]字符串指定窗口句柄。

此处无需实际窗口句柄。

顺便说一句,我发现这个解决方案是this forum post的绊脚石。我发现将搜索限制在我正在寻找的特定语言中通常很有帮助。大多数情况下,解决方案可以使用不同的语言找到,可以轻松移植到您选择的语言中。