如何处理使用 pywinauto 提取 MSI 的 Installshield 安装?

How do deal with Installshield installations that extract an MSI with pywinauto?

我正在尝试自动执行以 InstallShield setup.exe 开始的安装。这将启动 MS Visual C++ 可再发行组件的安装。这会导致有关 Adob​​e Flash 不是最新的错误。我在这里询问了如何处理:

单击 Adob​​e 对话框的“确定”后(目前必须使用 pyautogui.click()),我看到正在提取一个 .msi。我已经按照安装步骤将其放入我的 Users\AppData 目录下的一个新的 Temp 文件夹中。

如何让 pywinauto 找到这个新应用程序?我试过使用

adobe = Application().connect(title_re="MyInstaller",class_name="#32770", visible_only=True)

然后尝试 print_control_identifiers() 但出现此错误:

AttributeError:既未找到 GUI 元素(包装器)也未找到包装器方法 'print_control_identifiers'(打字错误?)

我检查了 Spy++ 和 Inspect 以及 AutoIT 以找到我能找到的 class。我不能使用 procid,因为它总是会改变。

关于如何附加到 .msi 进程以便我可以连接到它的任何想法?

编辑: 如果我知道 MyProgram.msi 在哪里,有没有办法让 regex pywinauto 指向一条路径?它似乎在 C:\Users\me\AppData\Local\Temp{xxx}\MyProgram.msi 中,因为我在那里找到了几个副本。谢谢!

添加 timeout=10 或任何您需要的 connect() 参数。当前默认超时为零,但它应该是 timings.Timings.window_find_timeout,默认为 5 秒。

计划在下一个主要版本中自动检测生成的子进程(以及默认超时修复)。

对于 运行 解压缩的 .msi 文件,您需要 msiexec 方法 .start() 中的标准 Windows 命令。首先从 msiexec /?.

开始手动玩 cmd.exe

以下是我如何处理 InstallShield exe 提取到 .msi 中(到我的 DownloadedInstallations 文件夹中)这一事实。是的,超时很重要,但识别打开的新 msi window 也很重要。 (此外,我发现 wait_for_idle 必须为 FALSE 但不记得为什么。YMMV :))。

exe = pywinauto.Application(backend="uia").start(exepath, wait_for_idle=False)

现在它将把 .exe 解压缩到 .msi 安装程序中,这可能需要一段时间,并且由于 .exe window 的名称可能与 .msi window 必须相同注意不要过早附加到 exe window 并且必须等待 .msi window 打开!!因此,以秒为单位添加适当的超时。对话框 window 在这里可能还不存在,所以使用 MsiDialogCloseClass 的 class_name 是至关重要的,尤其是当 exe 和 msi 的标题相同时。这将在 .msi window 到达时具体识别它。

title = "Enter Title of your App - InstallShield Wizard"
msi = pywinauto.Application(backend="uia").connect(title=title, 
class_name="MsiDialogCloseClass",timeout=120)

最后一点,在我总是忘记的一行中,必须再次使用标题才能获得对话框 window(由于我还不明白的原因)

dlg = msi[title]

此时查看所有控件标识符的非常有用的方法是:

print(dlg.print_control_identifiers())

这是经过数小时的反复试验得出的结果。要继续,现在您可以单击按钮,如下所示:

dlg.Next.wait("ready",timeout=2)
dlg.Next.click()

点击单选按钮,这个可行(可能还有其他方法,但我永远找不到如何按名称获取按钮的句柄)

dlg['I &accept the terms in the License Agreement'].wait('enabled').click()

然后继续

dlg.Next.click()
dlg.Install.wait("enabled",timeout=5)
dlg.Install.click()