АвтоматизиранС Π½Π° дСсктопСн GUI Π½Π° Python + pywinauto: ΠΊΠ°ΠΊ Π΄Π° сС ΡΡŠΡ‡Π΅Ρ‚Π°ΡΡ‚ c MS UI Automation

Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° Python pywinauto β€” Ρ‚ΠΎΠ²Π° Π΅ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ с ΠΎΡ‚Π²ΠΎΡ€Π΅Π½ ΠΊΠΎΠ΄ Π·Π° автоматизация Π½Π° настолни GUI прилоТСния Π² Windows. ΠŸΡ€Π΅Π· послСднитС Π΄Π²Π΅ Π³ΠΎΠ΄ΠΈΠ½ΠΈ сС появиха Π½ΠΎΠ²ΠΈ Π·Π½Π°Ρ‡ΠΈΡ‚Π΅Π»Π½ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ:

  • ΠŸΠΎΠ΄Π΄Ρ€ΡŠΠΆΠΊΠ° Π½Π° тСхнологията MS UI Automation. Π˜Π½Ρ‚Π΅Ρ€Ρ„Π΅ΠΉΡΡŠΡ‚ остава ΡΡŠΡ‰ΠΈΡΡ‚, ΠΈ сСга сС ΠΏΠΎΠ΄Π΄ΡŠΡ€ΠΆΠ°Ρ‚: WinForms, WPF, Qt5, Windows Store (UWP) ΠΈ ΠΌΠ½ΠΎΠ³ΠΎ Π΄Ρ€ΡƒΠ³ΠΈ β€” ΠΏΠΎΡ‡Ρ‚ΠΈ всичко, ΠΊΠΎΠ΅Ρ‚ΠΎ ΡΡŠΡ‰Π΅ΡΡ‚Π²ΡƒΠ²Π° Π² Windows.
  • БистСма Π·Π° Π±Π΅ΠΊΠ΅Π½Π΄ΠΈ/плъгини (Π² ΠΌΠΎΠΌΠ΅Π½Ρ‚Π° ΠΈΠΌΠ° Π΄Π²Π°: ΠΏΠΎ ΠΏΠΎΠ΄Ρ€Π°Π·Π±ΠΈΡ€Π°Π½Π΅ "win32" ΠΈ новия "uia"). Плавно сС насочвамС към крос-платформСност.
  • Win32 Ρ…ΡƒΠΊΠΎΠ²Π΅ Π·Π° мишка ΠΈ ΠΊΠ»Π°Π²ΠΈΠ°Ρ‚ΡƒΡ€Π° (Π³ΠΎΡ€Π΅Ρ‰ΠΈ клавиши Π² Π΄ΡƒΡ…Π° Π½Π° pyHook).

Π‘ΡŠΡ‰ΠΎ Ρ‚Π°ΠΊΠ° Ρ‰Π΅ Π½Π°ΠΏΡ€Π°Π²ΠΈΠΌ ΠΊΡ€Π°Ρ‚ΡŠΠΊ ΠΏΡ€Π΅Π³Π»Π΅Π΄ Π½Π° ΠΎΠΏΡ†ΠΈΠΈΡ‚Π΅ с ΠΎΡ‚Π²ΠΎΡ€Π΅Π½ ΠΊΠΎΠ΄ Π·Π° настойчива автоматизация (Π±Π΅Π· ΠΏΡ€Π΅Ρ‚Π΅Π½Ρ†ΠΈΠΈ Π·Π° сСриозно сравнСниС).

Π’Π°Π·ΠΈ статия Π΅ частично Ρ‚ΡŠΠ»ΠΊΡƒΠ²Π°Π½Π΅ Π½Π° Π΄ΠΎΠΊΠ»Π°Π΄ ΠΎΡ‚ конфСрСнцията SQA Days 20 Π² Минск (запис Π½Π° Π²ΠΈΠ΄Π΅ΠΎ ΠΈ слайдовС), частично Π±ΡŠΠ»Π³Π°Ρ€ΡΠΊΠ° вСрсия Π ΡŠΠΊΠΎΠ²ΠΎΠ΄ΡΡ‚Π²ΠΎ Π·Π° Π½Π°Ρ‡ΠΈΠ½Π°Π΅Ρ‰ΠΈ Π·Π° pywinauto.

НСка Π·Π°ΠΏΠΎΡ‡Π½Π΅ΠΌ с ΠΊΡ€Π°Ρ‚ΡŠΠΊ ΠΏΡ€Π΅Π³Π»Π΅Π΄ Π½Π° ΠΎΡ‚Π²ΠΎΡ€Π΅Π½ΠΈΡ‚Π΅ Ρ‚Π΅Ρ…Π½ΠΎΠ»ΠΎΠ³ΠΈΠΈ Π² Ρ‚Π°Π·ΠΈ област. Π—Π° настолни GUI прилоТСния Π΅ ΠΌΠ°Π»ΠΊΠΎ ΠΏΠΎ-слоТно, ΠΎΡ‚ΠΊΠΎΠ»ΠΊΠΎΡ‚ΠΎ Π·Π° ΡƒΠ΅Π±, ΠΊΠΎΠΉΡ‚ΠΎ ΠΈΠΌΠ° Selenium. Π•Ρ‚ΠΎ основнитС ΠΏΠΎΠ΄Ρ…ΠΎΠ΄ΠΈ:

ΠœΠ΅Ρ‚ΠΎΠ΄ Π½Π° ΠΊΠΎΠΎΡ€Π΄ΠΈΠ½Π°Ρ‚ΠΈΡ‚Π΅

Π₯Π°Ρ€Π΄ΠΊΠΎΠ΄ΠΈΠΌ Ρ‚ΠΎΡ‡ΠΊΠΈ Π½Π° ΠΊΠ»ΠΈΠΊΠ²Π°Π½Π΅, сС надявамС Π½Π° успСх.
[+] ΠšΡ€ΠΎΡ-ΠΏΠ»Π°Ρ‚Ρ„ΠΎΡ€ΠΌΠ΅Π½, лСсно Ρ€Π΅Π°Π»ΠΈΠ·ΠΈΡ€ΡƒΠ΅ΠΌ.
[+] ЛСсно Π΄Π° сС Π½Π°ΠΏΡ€Π°Π²ΠΈ "record-replay" запис Π½Π° тСстовС.
[-] Най-нСстабилСн към ΠΏΡ€ΠΎΠΌΠ΅Π½ΠΈ Π² Ρ€Π΅Π·ΠΎΠ»ΡŽΡ†ΠΈΡΡ‚Π° Π½Π° Π΅ΠΊrana, Ρ‚Π΅ΠΌΠΈ, ΡˆΡ€ΠΈΡ„Ρ‚ΠΎΠ²Π΅, Ρ€Π°Π·ΠΌΠ΅Ρ€ΠΈ Π½Π° ΠΏΡ€ΠΎΠ·ΠΎΡ€Ρ†ΠΈ ΠΈ Ρ‚.Π½.
[-] НСобходими са ΠΎΠ³Ρ€ΠΎΠΌΠ½ΠΈ усилия Π·Π° ΠΏΠΎΠ΄Π΄Ρ€ΡŠΠΆΠΊΠ°, чСсто Π΅ ΠΏΠΎ-лСсно Π΄Π° сС Π³Π΅Π½Π΅Ρ€ΠΈΡ€Π°Ρ‚ тСстовСтС ΠΎΡ‚ Π½ΡƒΠ»Π°Ρ‚Π° ΠΈΠ»ΠΈ Π΄Π° сС тСстват Ρ€ΡŠΡ‡Π½ΠΎ.
[-] Автоматизира само дСйствия, Π·Π° вСрификация ΠΈ ΠΈΠ·Π²Π»ΠΈΡ‡Π°Π½Π΅ Π½Π° Π΄Π°Π½Π½ΠΈ ΠΈΠΌΠ° Π΄Ρ€ΡƒΠ³ΠΈ ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΈ.

Π˜Π½ΡΡ‚Ρ€ΡƒΠΌΠ΅Π½Ρ‚ΠΈ (крос-ΠΏΠ»Π°Ρ‚Ρ„ΠΎΡ€ΠΌΠ΅Π½ΠΈ): autopy, PyAutoGUI, PyUserInput ΠΈ ΠΌΠ½ΠΎΠ³ΠΎ Π΄Ρ€ΡƒΠ³ΠΈ. ОбикновСно ΠΏΠΎ-слоТнитС инструмСнти Π²ΠΊΠ»ΡŽΡ‡Π²Π°Ρ‚ Ρ‚Π°Π·ΠΈ функционалност (Π½Π΅ Π²ΠΈΠ½Π°Π³ΠΈ крос-ΠΏΠ»Π°Ρ‚Ρ„ΠΎΡ€ΠΌΠ΅Π½ΠΈ).

Π‘Ρ‚Ρ€ΡƒΠ²Π° си Π΄Π° сС ΠΊΠ°ΠΆΠ΅, Ρ‡Π΅ ΠΌΠ΅Ρ‚ΠΎΠ΄ΡŠΡ‚ Π½Π° ΠΊΠΎΠΎΡ€Π΄ΠΈΠ½Π°Ρ‚ΠΈΡ‚Π΅ ΠΌΠΎΠΆΠ΅ Π΄Π° допълва останалитС ΠΏΠΎΠ΄Ρ…ΠΎΠ΄ΠΈ. НапримСр, Π·Π° собствСна Π³Ρ€Π°Ρ„ΠΈΠΊΠ° ΠΌΠΎΠΆΠ΅ Π΄Π° ΠΊΠ»ΠΈΠΊΠ½Π΅Ρ‚Π΅ Π½Π° относитСлни ΠΊΠΎΠΎΡ€Π΄ΠΈΠ½Π°Ρ‚ΠΈ (ΠΎΡ‚ лСвия Π³ΠΎΡ€Π΅Π½ ъгъл Π½Π° ΠΏΡ€ΠΎΠ·ΠΎΡ€Π΅Ρ†Π°/Π΅Π»Π΅ΠΌΠ΅Π½Ρ‚Π°, Π° Π½Π΅ Π½Π° цСлия Π΅ΠΊΡ€Π°Π½) β€” ΠΎΠ±ΠΈΠΊΠ½ΠΎΠ²Π΅Π½ΠΎ Ρ‚ΠΎΠ²Π° Π΅ Π΄ΠΎΡΡ‚Π°Ρ‚ΡŠΡ‡Π½ΠΎ Π½Π°Π΄Π΅ΠΆΠ΄Π½ΠΎ, особСно Π°ΠΊΠΎ Π²Π·Π΅ΠΌΠ΅ΠΌ ΠΏΡ€Π΅Π΄Π²ΠΈΠ΄ Π΄ΡŠΠ»ΠΆΠΈΠ½Π°Ρ‚Π°/ΡˆΠΈΡ€ΠΈΠ½Π°Ρ‚Π° Π½Π° цСлия Π΅Π»Π΅ΠΌΠ΅Π½Ρ‚ (Ρ‚ΠΎΠ³Π°Π²Π° ΠΈ Ρ€Π°Π·Π»ΠΈΡ‡Π½Π°Ρ‚Π° Ρ€Π΅Π·ΠΎΠ»ΡŽΡ†ΠΈΡ Π½Π° Π΅ΠΊΡ€Π°Π½Π° Π½Π΅ Π±ΠΈ ΠΏΠΎΠΏΡ€Π΅Ρ‡ΠΈΠ»Π°).

Π”Ρ€ΡƒΠ³ Π²Π°Ρ€ΠΈΠ°Π½Ρ‚: Π΄Π° сС ΠΈΠ·Π±Π΅Ρ€Π΅ само Π΅Π΄Π½Π° машина Π·Π° тСстовС със стабилни настройки (Π½Π΅ крос-ΠΏΠ»Π°Ρ‚Ρ„ΠΎΡ€ΠΌΠ΅Π½, Π½ΠΎ Π² някои случаи става).

Π Π°Π·ΠΏΠΎΠ·Π½Π°Π²Π°Π½Π΅ Π½Π° стандартни изобраТСния

[+] ΠšΡ€ΠΎΡ-ΠΏΠ»Π°Ρ‚Ρ„ΠΎΡ€ΠΌΠ΅Π½
[+-] ΠžΡ‚Π½ΠΎΡΠΈΡ‚Π΅Π»Π½ΠΎ Π½Π°Π΄Π΅ΠΆΠ΄Π΅Π½ (ΠΏΠΎ-Π΄ΠΎΠ±Ρ€Π΅ ΠΎΡ‚ координатния ΠΌΠ΅Ρ‚ΠΎΠ΄), Π½ΠΎ всС ΠΏΠ°ΠΊ изисква хитрости.
[-+] ΠžΡ‚Π½ΠΎΡΠΈΡ‚Π΅Π»Π½ΠΎ Π±Π°Π²Π΅Π½, Ρ‚ΡŠΠΉ ΠΊΠ°Ρ‚ΠΎ изисква рСсурситС Π½Π° CPU Π·Π° Π°Π»Π³ΠΎΡ€ΠΈΡ‚ΠΌΠΈ Π·Π° Ρ€Π°Π·ΠΏΠΎΠ·Π½Π°Π²Π°Π½Π΅.
[-] Π—Π° Ρ€Π°Π·ΠΏΠΎΠ·Π½Π°Π²Π°Π½Π΅ Π½Π° тСкст (OCR), ΠΎΠ±ΠΈΠΊΠ½ΠΎΠ²Π΅Π½ΠΎ няма Π³ΠΎΠ²ΠΎΡ€ => Π½Π΅ ΠΌΠΎΠΆΠ΅ Π΄Π° сС ΠΈΠ·Π²Π»Π΅ΠΊΠ°Ρ‚ тСкстови Π΄Π°Π½Π½ΠΈ. Π”ΠΎΠΊΠΎΠ»ΠΊΠΎΡ‚ΠΎ ΠΌΠΈ Π΅ извСстно, ΡΡŠΡ‰Π΅ΡΡ‚Π²ΡƒΠ²Π°Ρ‰ΠΈΡ‚Π΅ OCR Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ Π½Π΅ са особСно Π½Π°Π΄Π΅ΠΆΠ΄Π½ΠΈ Π·Π° Ρ‚ΠΎΠ·ΠΈ Ρ‚ΠΈΠΏ Π·Π°Π΄Π°Ρ‡ΠΈ ΠΈ Π½Π΅ сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚ ΡˆΠΈΡ€ΠΎΠΊΠΎ (Π΄ΠΎΠ±Ρ€Π΅ дошли Π² ΠΊΠΎΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΡ‚Π΅, Π°ΠΊΠΎ Ρ‚ΠΎΠ²Π° Π²Π΅Ρ‡Π΅ Π½Π΅ Π΅ Ρ‚Π°ΠΊΠ°).

Π˜Π½ΡΡ‚Ρ€ΡƒΠΌΠ΅Π½Ρ‚ΠΈ: Sikuli, Lackey (ΡΡŠΠ²ΠΌΠ΅ΡΡ‚ΠΈΠΌ с Sikuli, Π½Π° чист Python), PyAutoGUI.

Π’Π΅Ρ…Π½ΠΎΠ»ΠΎΠ³ΠΈΠΈ Π·Π° Π΄ΠΎΡΡ‚ΡŠΠΏΠ½ΠΎΡΡ‚

[+] Най-надСТдният ΠΌΠ΅Ρ‚ΠΎΠ΄, Ρ‚ΡŠΠΉ ΠΊΠ°Ρ‚ΠΎ позволява Ρ‚ΡŠΡ€ΡΠ΅Π½Π΅ ΠΏΠΎ тСкст, нСзависимо ΠΎΡ‚ Ρ‚ΠΎΠ²Π° ΠΊΠ°ΠΊ Π΅ нарисуван ΠΎΡ‚ систСмата ΠΈΠ»ΠΈ Ρ„Ρ€Π΅ΠΉΠΌΠ²ΠΎΡ€ΠΊΠ°.
[+] Позволява ΠΈΠ·Π²Π»ΠΈΡ‡Π°Π½Π΅ Π½Π° тСкстови Π΄Π°Π½Π½ΠΈ => ΠΏΠΎ-лСсно Π΅ Π΄Π° сС Π²Π΅Ρ€ΠΈΡ„ΠΈΡ†ΠΈΡ€Π°Ρ‚ Ρ€Π΅Π·ΡƒΠ»Ρ‚Π°Ρ‚ΠΈΡ‚Π΅ ΠΎΡ‚ тСстовСтС.
[+] ОбикновСно Π΅ Π½Π°ΠΉ-Π±ΡŠΡ€Π·ΠΈΡΡ‚, Ρ‚ΡŠΠΉ ΠΊΠ°Ρ‚ΠΎ ΠΏΠΎΡ‡Ρ‚ΠΈ Π½Π΅ ΠΈΠ·Ρ€Π°Π·Ρ…ΠΎΠ΄Π²Π° рСсурси Π½Π° CPU.
[-] Π’Ρ€ΡƒΠ΄Π½ΠΎ Π΅ Π΄Π° сС Π½Π°ΠΏΡ€Π°Π²ΠΈ крос-ΠΏΠ»Π°Ρ‚Ρ„ΠΎΡ€ΠΌΠ΅Π½ инструмСнт: Π°Π±ΡΠΎΠ»ΡŽΡ‚Π½ΠΎ всички open-source Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ ΠΏΠΎΠ΄Π΄ΡŠΡ€ΠΆΠ°Ρ‚ Π΅Π΄Π½Π°-Π΄Π²Π΅ Ρ‚Π΅Ρ…Π½ΠΎΠ»ΠΎΠ³ΠΈΠΈ Π·Π° Π΄ΠΎΡΡ‚ΡŠΠΏΠ½ΠΎΡΡ‚. Windows/Linux/MacOS Π½Π΅ сС ΠΏΠΎΠ΄Π΄ΡŠΡ€ΠΆΠ° напълно ΠΎΡ‚ Π½ΠΈΠΊΠΎΠ³ΠΎ, освСн ΠΎΡ‚ ΠΏΠ»Π°Ρ‚Π΅Π½ΠΈ ΠΊΠ°Ρ‚ΠΎ TestComplete, UFT ΠΈΠ»ΠΈ Squish.
[-] НС Π²ΠΈΠ½Π°Π³ΠΈ Ρ‚Π°ΠΊΠ°Π²Π° тСхнология Π΅ Π½Π°Π»ΠΈΡ‡Π½Π° ΠΈΠ·ΠΎΠ±Ρ‰ΠΎ. НапримСр, тСстванСто Π½Π° зарСТдащия Π΅ΠΊΡ€Π°Π½ Π²ΡŠΡ‚Ρ€Π΅ Π² VirtualBox β€” Ρ‚ΡƒΠΊ Π±Π΅Π· Ρ€Π°Π·ΠΏΠΎΠ·Π½Π°Π²Π°Π½Π΅ Π½Π° изобраТСния Π½Π΅ ΠΌΠΎΠΆΠ΅ Π΄Π° сС ΠΌΠΈΠ½Π΅. Но Π² ΠΌΠ½ΠΎΠ³ΠΎ класичСски случаи всС ΠΏΠ°ΠΊ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄ΡŠΡ‚ Π·Π° Π΄ΠΎΡΡ‚ΡŠΠΏΠ½ΠΎΡΡ‚ Π΅ ΠΏΡ€ΠΈΠ»ΠΎΠΆΠΈΠΌ. Π’ слСдващата част Ρ‰Π΅ станС Π²ΡŠΠΏΡ€ΠΎΡ Π·Π° Π½Π΅Π³ΠΎ.

Π˜Π½ΡΡ‚Ρ€ΡƒΠΌΠ΅Π½Ρ‚ΠΈ: TestStack.White Π½Π° C#, Winium.Desktop Π½Π° C# (ΡΡŠΠ²ΠΌΠ΅ΡΡ‚ΠΈΠΌ със Selenium), MS WinAppDriver Π½Π° C# (ΡΡŠΠ²ΠΌΠ΅ΡΡ‚ΠΈΠΌ с Appium), pywinauto, pyatom (ΡΡŠΠ²ΠΌΠ΅ΡΡ‚ΠΈΠΌ с LDTP), Python-UIAutomation-for-Windows, RAutomation Π½Π° Ruby, LDTP (Linux Desktop Testing Project) ΠΈ Π½Π΅Π³ΠΎΠ²Π°Ρ‚Π° Windows вСрсия Cobra.

LDTP β€” вСроятно СдинствСният крос-ΠΏΠ»Π°Ρ‚Ρ„ΠΎΡ€ΠΌΠ΅Π½ open-source инструмСнт (ΠΏΠΎ-скоро сСмСйство ΠΎΡ‚ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ) Π½Π° Π±Π°Π·Π°Ρ‚Π° Π½Π° Ρ‚Π΅Ρ…Π½ΠΎΠ»ΠΎΠ³ΠΈΠΈ Π·Π° Π΄ΠΎΡΡ‚ΡŠΠΏΠ½ΠΎΡΡ‚. Π’ΡŠΠΏΡ€Π΅ΠΊΠΈ Ρ‚ΠΎΠ²Π°, Ρ‚ΠΎΠΉ Π½Π΅ Π΅ особСно популярСн. Аз самият Π½Π΅ съм Π³ΠΎ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π», Π½ΠΎ ΠΏΠΎ ΠΎΡ‚Π·ΠΈΠ²ΠΈ ΠΈΠ½Ρ‚Π΅Ρ€Ρ„Π΅ΠΉΡΡŠΡ‚ ΠΌΡƒ Π½Π΅ Π΅ Π½Π°ΠΉ-удобният. Ако ΠΈΠΌΠ° ΠΏΠΎΠ·ΠΈΡ‚ΠΈΠ²Π½ΠΈ ΠΎΡ‚Π·ΠΈΠ²ΠΈ, моля, сподСлСтС Π² ΠΊΠΎΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΡ‚Π΅.

ВСстов backdoor (Π°.ΠΊ.Π°. Π²ΡŠΡ‚Ρ€Π΅ΡˆΠ΅Π½ вСлосипСд)

Π—Π° крос-ΠΏΠ»Π°Ρ‚Ρ„ΠΎΡ€ΠΌΠ΅Π½ΠΈ прилоТСния самитС Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΡ†ΠΈ чСсто ΡΡŠΠ·Π΄Π°Π²Π°Ρ‚ Π²ΡŠΡ‚Ρ€Π΅ΡˆΠ΅Π½ ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΡŠΠΌ Π·Π° осигуряванС Π½Π° testability. НапримСр, ΡΡŠΠ·Π΄Π°Π²Π°Ρ‚ слуТСбСн TCP ΡΡŠΡ€Π²ΡŠΡ€ Π² ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅Ρ‚ΠΎ, тСстовСтС сС ΡΠ²ΡŠΡ€Π·Π²Π°Ρ‚ към Π½Π΅Π³ΠΎ ΠΈ ΠΈΠ·ΠΏΡ€Π°Ρ‰Π°Ρ‚ тСкстови ΠΊΠΎΠΌΠ°Π½Π΄ΠΈ: ΠΊΠ°ΠΊΠ²ΠΎ Π΄Π° сС натиснС, ΠΎΡ‚ΠΊΡŠΠ΄Π΅ Π΄Π° сС Π²Π·Π΅ΠΌΠ°Ρ‚ Π΄Π°Π½Π½ΠΈ ΠΈ Ρ‚.Π½. НадСТдно, Π½ΠΎ Π½Π΅ унивСрсално.

Основни Ρ‚Π΅Ρ…Π½ΠΎΠ»ΠΎΠ³ΠΈΠΈ Π·Π° настолна Π΄ΠΎΡΡ‚ΡŠΠΏΠ½ΠΎΡΡ‚

Бтарият Π΄ΠΎΠ±ΡŠΡ€ Win32 API

ΠŸΠΎΠ²Π΅Ρ‡Π΅Ρ‚ΠΎ Windows прилоТСния, написани ΠΏΡ€Π΅Π΄ΠΈ WPF ΠΈ слСд Ρ‚ΠΎΠ²Π° Windows Store, са ΠΈΠ·Π³Ρ€Π°Π΄Π΅Π½ΠΈ ΠΏΠΎ Π΅Π΄ΠΈΠ½ ΠΈΠ»ΠΈ Π΄Ρ€ΡƒΠ³ Π½Π°Ρ‡ΠΈΠ½ Π½Π° Win32 API. А ΠΈΠΌΠ΅Π½Π½ΠΎ, MFC, WTL, C++ Builder, Delphi, VB6 β€” всички Ρ‚Π΅Π·ΠΈ инструмСнти ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚ Win32 API. Π”ΠΎΡ€ΠΈ Windows Forms β€” Π² Π·Π½Π°Ρ‡ΠΈΡ‚Π΅Π»Π½Π° стСпСн ΡΡŠΠ²ΠΌΠ΅ΡΡ‚ΠΈΠΌΠΈ с Win32 API.

Π˜Π½ΡΡ‚Ρ€ΡƒΠΌΠ΅Π½Ρ‚ΠΈ: AutoIt (ΠΏΠΎΠ΄ΠΎΠ±Π΅Π½ Π½Π° VB) ΠΈ Python ΠΎΠ±Π²ΠΈΠ²ΠΊΠ° pyautoit, AutoHotkey (собствСн Π΅Π·ΠΈΠΊ, ΠΈΠΌΠ° IDispatch COM интСрфСйс), pywinauto (Python), RAutomation (Ruby), win32-autogui (Ruby).

Microsoft UI Automation

ΠžΡΠ½ΠΎΠ²Π½ΠΎΡ‚ΠΎ прСдимство: тСхнологията MS UI Automation ΠΏΠΎΠ΄Π΄ΡŠΡ€ΠΆΠ° ΠΎΠ³Ρ€ΠΎΠΌΠ½ΠΎΡ‚ΠΎ мнозинство ΠΎΡ‚ GUI прилоТСния Π½Π° Windows с Ρ€Π΅Π΄ΠΊΠΈ ΠΈΠ·ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ. ΠŸΡ€ΠΎΠ±Π»Π΅ΠΌΡŠΡ‚: тя Π½Π΅ Π΅ ΠΌΠ½ΠΎΠ³ΠΎ ΠΏΠΎ-лСсна Π·Π° ΠΈΠ·ΡƒΡ‡Π°Π²Π°Π½Π΅ ΠΎΡ‚ Win32 API. Π’ ΠΏΡ€ΠΎΡ‚ΠΈΠ²Π΅Π½ случай Π½ΠΈΠΊΠΎΠΉ нямашС Π΄Π° ΠΏΡ€Π°Π²ΠΈ ΠΎΠ±Π²ΠΈΠ²ΠΊΠΈ Π½Π°Π΄ нСя.

Π’ΡΡŠΡ‰Π½ΠΎΡΡ‚, Ρ‚ΠΎΠ²Π° Π΅ Π½Π°Π±ΠΎΡ€ ΠΎΡ‚ custom COM интСрфСйси (ΠΏΡ€Π΅Π΄ΠΈΠΌΠ½ΠΎ, UIAutomationCore.dll), Π° ΡΡŠΡ‰ΠΎ Ρ‚Π°ΠΊΠ° ΠΈΠΌΠ° .NET ΠΎΠ±Π²ΠΈΠ²ΠΊΠ° ΠΏΠΎΠ΄ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚Π° Π½Π° namespace System.Windows.Automation. ΠœΠ΅ΠΆΠ΄Ρƒ Π΄Ρ€ΡƒΠ³ΠΎΡ‚ΠΎ, тя ΠΈΠΌΠ° внСсСн бъг, ΠΏΠΎΡ€Π°Π΄ΠΈ ΠΊΠΎΠΉΡ‚ΠΎ някои UI Π΅Π»Π΅ΠΌΠ΅Π½Ρ‚ΠΈ ΠΌΠΎΠ³Π°Ρ‚ Π΄Π° Π±ΡŠΠ΄Π°Ρ‚ пропуснати. Π—Π°Ρ‚ΠΎΠ²Π° Π΅ ΠΏΠΎ-Π΄ΠΎΠ±Ρ€Π΅ Π΄Π° сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° UIAutomationCore.dll Π΄ΠΈΡ€Π΅ΠΊΡ‚Π½ΠΎ (Π°ΠΊΠΎ стС Ρ‡ΡƒΠ²Π°Π»ΠΈ Π·Π° UiaComWrapper Π½Π° C#, Ρ‚ΠΎΠ²Π° Π΅ Ρ‚ΠΎ).

Π’ΠΈΠ΄ΠΎΠ²Π΅ COM интСрфСйси:

(1) ОсновСн IUknown β€” β€žΠΊΠΎΡ€Π΅Π½ΡŠΡ‚ Π½Π° Π·Π»ΠΎΡ‚ΠΎβ€œ. Най-ниското Π½ΠΈΠ²ΠΎ, Π½ΠΈΠΊΠ°ΠΊ Π½Π΅ user-friendly.
(2) IDispatch ΠΈ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄Π½ΠΈ (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Excel.Application), ΠΊΠΎΠΈΡ‚ΠΎ ΠΌΠΎΠ³Π°Ρ‚ Π΄Π° сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚ Π² Python с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° ΠΏΠ°ΠΊΠ΅Ρ‚Π° win32com.client (Π²ΠΊΠ»ΡŽΡ‡Π΅Π½ Π² pyWin32). Най-удобният ΠΈ красив Π²Π°Ρ€ΠΈΠ°Π½Ρ‚.
(3) Custom интСрфСйси, с ΠΊΠΎΠΈΡ‚ΠΎ Ρ€Π°Π±ΠΎΡ‚ΠΈ външСн Python ΠΏΠ°ΠΊΠ΅Ρ‚ comtypes.

Π˜Π½ΡΡ‚Ρ€ΡƒΠΌΠ΅Π½Ρ‚ΠΈ: TestStack.White Π½Π° C#, pywinauto 0.6.0+, Winium.Desktop Π½Π° C#, Python-UIAutomation-for-Windows (тяхният ΠΈΠ·Ρ…ΠΎΠ΄Π΅Π½ ΠΊΠΎΠ΄ Π½Π° C ΠΎΠ±Π²ΠΈΠ²ΠΊΠΈ Π½Π°Π΄ UIAutomationCore.dll Π½Π΅ Π΅ Ρ€Π°Π·ΠΊΡ€ΠΈΡ‚), RAutomation Π½Π° Ruby.

AT-SPI

Π’ΡŠΠΏΡ€Π΅ΠΊΠΈ Ρ‡Π΅ ΠΏΠΎΡ‡Ρ‚ΠΈ всички дистрибуции ΠΎΡ‚ сСмСйството Π½Π° Linux са построСни Π²ΡŠΡ€Ρ…Ρƒ X Window System (Π² Fedora 25 β€žΠΈΠΊΡΠΈΡ‚Π΅β€œ бяха Π·Π°ΠΌΠ΅Π½Π΅Π½ΠΈ с Wayland), β€žΠΈΠΊΡΠΈΡ‚Π΅β€œ позволяват Ρ€Π°Π±ΠΎΡ‚Π° само с ΠΏΡ€ΠΎΠ·ΠΎΡ€Ρ†ΠΈ Π½Π° Π²ΡŠΡ€Ρ…ΠΎΠ²ΠΎ Π½ΠΈΠ²ΠΎ ΠΈ мишка/ΠΊΠ»Π°Π²ΠΈΠ°Ρ‚ΡƒΡ€Π°. Π—Π° ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π΅Π½ Π°Π½Π°Π»ΠΈΠ· ΠΏΠΎ Π±ΡƒΡ‚ΠΎΠ½ΠΈ, ΡΠΏΠΈΡΡŠΡ‡Π½ΠΈ ΠΊΡƒΡ‚ΠΈΠΈ ΠΈ Ρ‚.Π½. β€” ΡΡŠΡ‰Π΅ΡΡ‚Π²ΡƒΠ²Π° тСхнология AT-SPI. Най-популярнитС ΠΏΡ€ΠΎΠ·ΠΎΡ€Π΅Ρ‡Π½ΠΈ ΠΌΠ΅Π½ΠΈΠ΄ΠΆΡŠΡ€ΠΈ ΠΈΠΌΠ°Ρ‚ Ρ‚Π°ΠΊΠ° нарСчСния AT-SPI рСгистров Π΄Π΅ΠΌΠΎΠ½, ΠΊΠΎΠΉΡ‚ΠΎ осигурява Π°Π²Ρ‚ΠΎΠΌΠ°Ρ‚ΠΈΠ·ΠΈΡ€ΡƒΠ΅ΠΌ GUI Π·Π° прилоТСния (ΠΊΠ°ΠΊΡ‚ΠΎ ΠΌΠΈΠ½ΠΈΠΌΡƒΠΌ ΠΏΠΎΠ΄Π΄ΡŠΡ€ΠΆΠ°Ρ‚ Qt ΠΈ GTK).

Π˜Π½ΡΡ‚Ρ€ΡƒΠΌΠ΅Π½Ρ‚ΠΈ: pyatspi2.

pyatspi2, Π½Π° ΠΌΠΎΠ΅ ΠΌΠ½Π΅Π½ΠΈΠ΅, ΡΡŠΠ΄ΡŠΡ€ΠΆΠ° Ρ‚Π²ΡŠΡ€Π΄Π΅ ΠΌΠ½ΠΎΠ³ΠΎ зависимости ΠΎΡ‚ Ρ‚ΠΈΠΏΠ° Π½Π° ΡΡŠΡ‰ΠΈΡ PyGObject. Π‘Π°ΠΌΠ°Ρ‚Π° тСхнология Π΅ Π΄ΠΎΡΡ‚ΡŠΠΏΠ½Π° ΠΏΠΎΠ΄ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚Π° Π½Π° ΠΎΠ±ΠΈΠΊΠ½ΠΎΠ²Π΅Π½Π° Π΄ΠΈΠ½Π°ΠΌΠΈΡ‡Π½Π° Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° libatspi.so. Има Reference Manual. Π—Π° Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ°Ρ‚Π° pywinauto ΠΏΠ»Π°Π½ΠΈΡ€Π°ΠΌΠ΅ Π΄Π° Ρ€Π΅Π°Π»ΠΈΠ·ΠΈΡ€Π°ΠΌΠ΅ ΠΏΠΎΠ΄Π΄Ρ€ΡŠΠΆΠΊΠ° Π½Π° AT-SPI Ρ‚ΠΎΡ‡Π½ΠΎ Ρ‚Π°ΠΊΠ°: Ρ‡Ρ€Π΅Π· Π·Π°Ρ€Π΅ΠΆΠ΄Π°Π½Π΅ Π½Π° libatspi.so ΠΈ ΠΌΠΎΠ΄ΡƒΠ» ctypes. Има малък ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌ само Π² ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅Ρ‚ΠΎ Π½Π° Π½ΡƒΠΆΠ½Π°Ρ‚Π° вСрсия, Ρ‚ΡŠΠΉ ΠΊΠ°Ρ‚ΠΎ Π·Π° прилоТСнията Π½Π° GTK+ ΠΈ Qt Ρ‚Π΅ са ΠΌΠ°Π»ΠΊΠΎ Ρ€Π°Π·Π»ΠΈΡ‡Π½ΠΈ. ВСроятният Ρ€Π΅Π»ΠΈΠ· Π½Π° pywinauto 0.7.0 с пълна ΠΏΠΎΠ΄Π΄Ρ€ΡŠΠΆΠΊΠ° Π·Π° Linux ΠΌΠΎΠΆΠ΅ Π΄Π° сС ΠΎΡ‡Π°ΠΊΠ²Π° ΠΏΡ€Π΅Π· ΠΏΡŠΡ€Π²Π°Ρ‚Π° ΠΏΠΎΠ»ΠΎΠ²ΠΈΠ½Π° Π½Π° 2018 Π³.

Apple Accessibility API

Π’ MacOS ΠΈΠΌΠ° собствСн Π΅Π·ΠΈΠΊ Π·Π° автоматизация AppleScript. Π—Π° Ρ€Π΅Π°Π»ΠΈΠ·ΠΈΡ€Π°Π½Π΅ Π½Π° Π½Π΅Ρ‰ΠΎ ΠΏΠΎΠ΄ΠΎΠ±Π½ΠΎ Π² Python, Ρ€Π°Π·Π±ΠΈΡ€Π° сС, трябва Π΄Π° сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΎΡ‚ ObjectiveC. Π—Π°ΠΏΠΎΡ‡Π²Π°ΠΉΠΊΠΈ, ΠΈΠ·Π³Π»Π΅ΠΆΠ΄Π°, ΠΎΡ‰Π΅ ΠΎΡ‚ MacOS 10.6, Π² ΠΏΡ€Π΅Π΄Π²Π°Ρ€ΠΈΡ‚Π΅Π»Π½ΠΎ инсталираната вСрсия Π½Π° Python сС Π²ΠΊΠ»ΡŽΡ‡Π²Π° ΠΏΠ°ΠΊΠ΅Ρ‚ΡŠΡ‚ pyobjc. Π’ΠΎΠ²Π° ΡΡŠΡ‰ΠΎ Ρ‚Π°ΠΊΠ° Ρ‰Π΅ опрости списъка с зависимости Π·Π° Π±ΡŠΠ΄Π΅Ρ‰Π° ΠΏΠΎΠ΄Π΄Ρ€ΡŠΠΆΠΊΠ° Π² pywinauto.

Π˜Π½ΡΡ‚Ρ€ΡƒΠΌΠ΅Π½Ρ‚ΠΈ: ОсвСн Π΅Π·ΠΈΠΊΠ° Apple Script, трябва Π΄Π° ΠΎΠ±ΡŠΡ€Π½Π΅Ρ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅ Π½Π° ATOMac, извСстСн ΠΎΡ‰Π΅ ΠΊΠ°Ρ‚ΠΎ pyatom. Π’ΠΎΠΉ Π΅ ΡΡŠΠ²ΠΌΠ΅ΡΡ‚ΠΈΠΌ ΠΏΠΎ интСрфСйса с LDTP, Π½ΠΎ ΡΡŠΡ‰ΠΎ Ρ‚Π°ΠΊΠ° Π΅ самостоятСлна Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ°. Има ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Π·Π° автоматизация Π½Π° iTunes Π² macOS, написан ΠΎΡ‚ моя студСнт. Има извСстСн ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌ: Π½Π΅ работят Π³ΡŠΠ²ΠΊΠ°Π²ΠΈΡ‚Π΅ Ρ‚Π°ΠΉΠΌΠΈΠ½Π³ΠΈ (ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΈΡ‚Π΅ waitFor*). Но, ΠΊΠ°Ρ‚ΠΎ цяло, Π΅ Π½Π΅ΠΏΠ»ΠΎΡ…Π° Ρ€Π°Π±ΠΎΡ‚Π°.

Как Π΄Π° Π·Π°ΠΏΠΎΡ‡Π½Π΅Ρ‚Π΅ Ρ€Π°Π±ΠΎΡ‚Π° с pywinauto

ΠŸΡŠΡ€Π²ΠΎΠ½Π°Ρ‡Π°Π»Π½ΠΎ Π΅ Π΄ΠΎΠ±Ρ€Π΅ Π΄Π° сС Π΅ΠΊΠΈΠΏΠΈΡ€Π°Ρ‚Π΅ с инспСктора Π½Π° GUI ΠΎΠ±Π΅ΠΊΡ‚ΠΈ (Ρ‚ΠΎΠ²Π°, ΠΊΠΎΠ΅Ρ‚ΠΎ Π½Π°Ρ€ΠΈΡ‡Π°Ρ‚ Spy tool). Π’ΠΎΠΉ Ρ‰Π΅ ΠΏΠΎΠΌΠΎΠ³Π½Π΅ Π΄Π° сС ΠΈΠ·ΡƒΡ‡ΠΈ ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅Ρ‚ΠΎ ΠΎΡ‚Π²ΡŠΡ‚Ρ€Π΅: ΠΊΠ°ΠΊ Π΅ ΠΈΠ·Π³Ρ€Π°Π΄Π΅Π½Π° йСрархията Π½Π° Π΅Π»Π΅ΠΌΠ΅Π½Ρ‚ΠΈΡ‚Π΅, ΠΊΠ°ΠΊΠ²ΠΈ свойства са Π½Π°Π»ΠΈΡ‡Π½ΠΈ. Най-извСстнитС инспСктори Π½Π° ΠΎΠ±Π΅ΠΊΡ‚ΠΈ са:

  • Spy++ β€” част ΠΎΡ‚ Visual Studio, Π²ΠΊΠ»ΡŽΡ‡ΠΈΡ‚Π΅Π»Π½ΠΎ Express ΠΈΠ»ΠΈ Community Edition. Използва Win32 API. Π‘ΡŠΡ‰ΠΎ Ρ‚Π°ΠΊΠ° Π΅ извСстСн ΠΊΠ»ΠΎΠ½ΡŠΡ‚ ΠΌΡƒ AutoIt Window Info.
  • Inspect.exe β€” част ΠΎΡ‚ Windows SDK. Ако Π΅ инсталиран, ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° Π³ΠΎ Π½Π°ΠΌΠ΅Ρ€ΠΈΡ‚Π΅ Π½Π° 64-Π±ΠΈΡ‚ΠΎΠ²Π° Windows Π² ΠΏΠ°ΠΏΠΊΠ°Ρ‚Π° C:Program Files (x86)Windows Kits<winver>binx64. Π’ самия инспСктор Π΅ Π½ΡƒΠΆΠ½ΠΎ Π΄Π° ΠΈΠ·Π±Π΅Ρ€Π΅Ρ‚Π΅ Ρ€Π΅ΠΆΠΈΠΌ UI Automation вмСсто MS AA (Active Accessibility, ΠΏΡ€Π΅Π΄ΡˆΠ΅ΡΡ‚Π²Π΅Π½ΠΈΠΊ Π½Π° UI Automation).

Π‘Π»Π΅Π΄ ΠΊΠ°Ρ‚ΠΎ Ρ€Π°Π·Π³Π»Π΅Π΄Π°Ρ‚Π΅ ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅Ρ‚ΠΎ, ΠΈΠ·Π±ΠΈΡ€Π°Ρ‚Π΅ Π±Π΅ΠΊΠ΅Π½Π΄Π°, ΠΊΠΎΠΉΡ‚ΠΎ Ρ‰Π΅ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚Π΅. Π”ΠΎΡΡ‚Π°Ρ‚ΡŠΡ‡Π½ΠΎ Π΅ Π΄Π° посочитС ΠΈΠΌΠ΅Ρ‚ΠΎ Π½Π° Π±Π΅ΠΊΠ΅Π½Π΄Π° ΠΏΡ€ΠΈ създаванС Π½Π° ΠΎΠ±Π΅ΠΊΡ‚ Application.

  • backend=Β»win32β€³ β€” всС ΠΎΡ‰Π΅ сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° ΠΏΠΎ ΠΏΠΎΠ΄Ρ€Π°Π·Π±ΠΈΡ€Π°Π½Π΅, Π΄ΠΎΠ±Ρ€Π΅ Ρ€Π°Π±ΠΎΡ‚ΠΈ с MFC, WTL, VB6 ΠΈ Π΄Ρ€ΡƒΠ³ΠΈ наслСдствСни прилоТСния.
  • backend=Β»uiaΒ» β€” Π½ΠΎΠ² Π±Π΅ΠΊΠ΅Π½Π΄ Π·Π° MS UI Automation: ΠΈΠ΄Π΅Π°Π»Π½ΠΎ Ρ€Π°Π±ΠΎΡ‚ΠΈ с WPF ΠΈ WinForms; ΡΡŠΡ‰ΠΎ Π΅ Π΄ΠΎΠ±ΡŠΡ€ Π·Π° прилоТСния Π½Π° Delphi ΠΈ Windows Store; Ρ€Π°Π±ΠΎΡ‚ΠΈ с Qt5 ΠΈ някои Java прилоТСния. И ΠΊΠ°Ρ‚ΠΎ цяло, Π°ΠΊΠΎ Inspect.exe Π²ΠΈΠΆΠ΄Π° Π΅Π»Π΅ΠΌΠ΅Π½Ρ‚ΠΈΡ‚Π΅ ΠΈ Ρ‚Π΅Ρ…Π½ΠΈΡ‚Π΅ свойства, Π·Π½Π°Ρ‡ΠΈ Ρ‚ΠΎΠ·ΠΈ Π±Π΅ΠΊΠ΅Π½Π΄ Π΅ подходящ. Π’ΡΡŠΡ‰Π½ΠΎΡΡ‚, ΠΏΠΎΠ²Π΅Ρ‡Π΅Ρ‚ΠΎ Π±Ρ€Π°ΡƒΠ·ΡŠΡ€ΠΈ ΡΡŠΡ‰ΠΎ ΠΏΠΎΠ΄Π΄ΡŠΡ€ΠΆΠ°Ρ‚ UI Automation (Mozilla ΠΏΠΎ ΠΏΠΎΠ΄Ρ€Π°Π·Π±ΠΈΡ€Π°Π½Π΅, Π° Π·Π° Chrome ΠΏΡ€ΠΈ стартиранС Π΅ Π½ΡƒΠΆΠ½ΠΎ Π΄Π° ΠΌΡƒ ΠΏΠΎΠ΄Π°Π΄Π΅Ρ‚Π΅ ΠΊΠΎΠΌΠ°Π½Π΄Π΅Π½ ΠΊΠ»ΡŽΡ‡ --force-renderer-accessibility, Π·Π° Π΄Π° Π²ΠΈΠ΄ΠΈΡ‚Π΅ Π΅Π»Π΅ΠΌΠ΅Π½Ρ‚ΠΈΡ‚Π΅ Π½Π° страницитС Π² Inspect.exe). Π Π°Π·Π±ΠΈΡ€Π° сС, конкурСнцията с Selenium Π² Ρ‚Π°Π·ΠΈ област Π΅Π΄Π²Π° Π»ΠΈ Π΅ възмоТна. ΠŸΡ€ΠΎΡΡ‚ΠΎ ΠΎΡ‰Π΅ Π΅Π΄ΠΈΠ½ Π½Π°Ρ‡ΠΈΠ½ Π·Π° Ρ€Π°Π±ΠΎΡ‚Π° с Π±Ρ€Π°ΡƒΠ·ΡŠΡ€ (ΠΌΠΎΠΆΠ΅ Π΄Π° Π΅ ΠΏΠΎΠ»Π΅Π·Π΅Π½ Π·Π° крос-ΠΏΡ€ΠΎΠ΄ΡƒΠΊΡ‚ΠΎΠ²ΠΈ сцСнарии).

Π’ΠΎΡ‡ΠΊΠΈ Π·Π° Π²Ρ…ΠΎΠ΄ Π·Π° автоматизация

ΠŸΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅Ρ‚ΠΎ Π΅ Π΄ΠΎΡΡ‚Π°Ρ‚ΡŠΡ‡Π½ΠΎ ΠΏΡ€ΠΎΡƒΡ‡Π΅Π½ΠΎ. Π’Ρ€Π΅ΠΌΠ΅ Π΅ Π΄Π° ΡΡŠΠ·Π΄Π°Π΄Π΅Ρ‚Π΅ ΠΎΠ±Π΅ΠΊΡ‚ Application ΠΈ Π΄Π° Π³ΠΎ стартиратС ΠΈΠ»ΠΈ Π΄Π° сС ΠΏΡ€ΠΈΡΡŠΠ΅Π΄ΠΈΠ½ΠΈΡ‚Π΅ към Π²Π΅Ρ‡Π΅ стартирано. Π’ΠΎΠ²Π° Π½Π΅ Π΅ просто ΠΊΠ»ΠΎΠ½ΠΈΠ½Π³ Π½Π° стандартния клас subprocess.Popen, ΠΈΠΌΠ΅Π½Π½ΠΎ въвСдСн ΠΎΠ±Π΅ΠΊΡ‚, ΠΊΠΎΠΉΡ‚ΠΎ ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π°Π²Π° всички ваши дСйствия Π² Π³Ρ€Π°Π½ΠΈΡ†ΠΈΡ‚Π΅ Π½Π° процСса. Π’ΠΎΠ²Π° Π΅ ΠΌΠ½ΠΎΠ³ΠΎ ΠΏΠΎΠ»Π΅Π·Π½ΠΎ, Π°ΠΊΠΎ са стартирани няколко инстанции Π½Π° ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅Ρ‚ΠΎ, Π° Π½Π΅ искатС Π΄Π° засягатС останалитС.

from pywinauto.application import Application
app = Application(backend="uia").start('notepad.exe')

# ОписвамС ΠΏΡ€ΠΎΠ·ΠΎΡ€Π΅Ρ†Π°, ΠΊΠΎΠΉΡ‚ΠΎ искамС Π΄Π° Π½Π°ΠΌΠ΅Ρ€ΠΈΠΌ Π² процСса Notepad.exe
dlg_spec = app.UntitledNotepad
# ΠΈΠ·Ρ‡Π°ΠΊΠ²Π°ΠΌΠ΅ ΠΏΡ€ΠΎΠ·ΠΎΡ€Π΅Ρ†ΡŠΡ‚ наистина Π΄Π° сС появи
actionable_dlg = dlg_spec.wait('visible')

Ако искатС Π΄Π° управляватС Π²Π΅Π΄Π½Π°Π³Π° няколко прилоТСния, ΠΊΠ»Π°ΡΡŠΡ‚ Ρ‰Π΅ Π²ΠΈ ΠΏΠΎΠΌΠΎΠ³Π½Π΅ Π Π°Π±ΠΎΡ‚Π΅Π½ ΠΏΠ»ΠΎΡ‚. НапримСр, Π² ΠΊΠ°Π»ΠΊΡƒΠ»Π°Ρ‚ΠΎΡ€Π° Π½Π° Win10 иСрархията Π½Π° Π΅Π»Π΅ΠΌΠ΅Π½Ρ‚ΠΈΡ‚Π΅ Π΅ Ρ€Π°Π·ΠΏΡŠΠ½Π°Ρ‚Π° ΠΏΠΎ няколко процСса (Π½Π΅ само calc.exe). Π’Π°ΠΊΠ° Ρ‡Π΅ Π±Π΅Π· ΠΎΠ±Π΅ΠΊΡ‚ Π Π°Π±ΠΎΡ‚Π΅Π½ ΠΏΠ»ΠΎΡ‚ Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° ΠΌΠΈΠ½Π΅Ρ‚Π΅.

from subprocess import Popen
from pywinauto import Desktop

Popen('calc.exe', shell=True)
dlg = Desktop(backend="uia").Calculator
dlg.wait('visible')

ΠšΠΎΡ€Π΅Π½ΠΎΠ²ΠΈΡΡ‚ ΠΎΠ±Π΅ΠΊΡ‚ (ΠŸΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ ΠΈΠ»ΠΈ Π Π°Π±ΠΎΡ‚Π΅Π½ ΠΏΠ»ΠΎΡ‚) Π΅ СдинствСното място, ΠΊΡŠΠ΄Π΅Ρ‚ΠΎ трябва Π΄Π° посочитС Π±Π΅ΠΊΠ΅Π½Π΄Π°. Всичко останало ΠΏΡ€ΠΎΠ·Ρ€Π°Ρ‡Π½ΠΎ сС вписва Π² концСпцията "спСцификация->ΠΎΠ±Π²ΠΈΠ²ΠΊΠ°", Π·Π° която Ρ‰Π΅ станС Π²ΡŠΠΏΡ€ΠΎΡ ΠΏΠΎ-Π½Π°Ρ‚Π°Ρ‚ΡŠΠΊ.

Π‘ΠΏΠ΅Ρ†ΠΈΡ„ΠΈΠΊΠ°Ρ†ΠΈΠΈ Π½Π° ΠΏΡ€ΠΎΠ·ΠΎΡ€Ρ†ΠΈ/Π΅Π»Π΅ΠΌΠ΅Π½Ρ‚ΠΈ

Π’ΠΎΠ²Π° Π΅ основната концСпция, Π½Π° която сС Π±Π°Π·ΠΈΡ€Π° ΠΈΠ½Ρ‚Π΅Ρ€Ρ„Π΅ΠΉΡΡŠΡ‚ Π½Π° pywinauto. ΠœΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° ΠΎΠΏΠΈΡˆΠ΅Ρ‚Π΅ ΠΏΡ€ΠΎΠ·ΠΎΡ€Π΅Ρ†/Π΅Π»Π΅ΠΌΠ΅Π½Ρ‚ ΠΏΡ€ΠΈΠ±Π»ΠΈΠ·ΠΈΡ‚Π΅Π»Π½ΠΎ ΠΈΠ»ΠΈ ΠΏΠΎ-ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π½ΠΎ, Π΄ΠΎΡ€ΠΈ Π°ΠΊΠΎ Ρ‚ΠΎΠΉ всС ΠΎΡ‰Π΅ Π½Π΅ ΡΡŠΡ‰Π΅ΡΡ‚Π²ΡƒΠ²Π° ΠΈΠ»ΠΈ Π²Π΅Ρ‡Π΅ Π΅ Π·Π°Ρ‚Π²ΠΎΡ€Π΅Π½. БпСцификацията Π½Π° ΠΏΡ€ΠΎΠ·ΠΎΡ€Π΅Ρ†Π° (ΠΎΠ±Π΅ΠΊΡ‚ WindowSpecification) ΡΡŠΡ…Ρ€Π°Π½ΡΠ²Π° ΠΊΡ€ΠΈΡ‚Π΅Ρ€ΠΈΠΈΡ‚Π΅, ΠΏΠΎ ΠΊΠΎΠΈΡ‚ΠΎ Π΄Π° сС Ρ‚ΡŠΡ€ΡΠΈ Ρ€Π΅Π°Π»Π΅Π½ ΠΏΡ€ΠΎΠ·ΠΎΡ€Π΅Ρ† ΠΈΠ»ΠΈ Π΅Π»Π΅ΠΌΠ΅Π½Ρ‚.

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ Π·Π° Π΄Π΅Ρ‚Π°ΠΉΠ»Π½Π° спСцификация Π½Π° ΠΏΡ€ΠΎΠ·ΠΎΡ€Π΅Ρ†Π°:

>>> dlg_spec = app.window(title='Untitled - Notepad')

>>> dlg_spec


>>> dlg_spec.wrapper_object()

Π‘Π°ΠΌΠΎΡ‚ΠΎ Ρ‚ΡŠΡ€ΡΠ΅Π½Π΅ Π½Π° ΠΏΡ€ΠΎΠ·ΠΎΡ€Π΅Ρ†Π° сС ΠΈΠ·Π²ΡŠΡ€ΡˆΠ²Π° Ρ‡Ρ€Π΅Π· ΠΈΠ·Π²ΠΈΠΊΠ²Π°Π½Π΅Ρ‚ΠΎ Π½Π° ΠΌΠ΅Ρ‚ΠΎΠ΄Π° .wrapper_object(). Π’ΠΎΠΉ Π²Ρ€ΡŠΡ‰Π° някакъв "ΠΎΠ±Π²ΠΈΠ²ΠΊΠ°" Π·Π° рСалния ΠΏΡ€ΠΎΠ·ΠΎΡ€Π΅Ρ†/Π΅Π»Π΅ΠΌΠ΅Π½Ρ‚ ΠΈΠ»ΠΈ Ρ…Π²ΡŠΡ€Π»Ρ ElementNotFoundError (понякога ElementAmbiguousError, Π°ΠΊΠΎ са Π½Π°ΠΌΠ΅Ρ€Π΅Π½ΠΈ няколко Π΅Π»Π΅ΠΌΠ΅Π½Ρ‚Π°, Ρ‚.Π΅. Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Π΅ Π΄Π° сС уточнят ΠΊΡ€ΠΈΡ‚Π΅Ρ€ΠΈΠΈΡ‚Π΅ Π·Π° Ρ‚ΡŠΡ€ΡΠ΅Π½Π΅). Π’Π°Π·ΠΈ "ΠΎΠ±Π²ΠΈΠ²ΠΊΠ°" Π²Π΅Ρ‡Π΅ ΠΌΠΎΠΆΠ΅ Π΄Π° ΠΈΠ·Π²ΡŠΡ€ΡˆΠ²Π° ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈ дСйствия с Π΅Π»Π΅ΠΌΠ΅Π½Ρ‚Π° ΠΈΠ»ΠΈ Π΄Π° ΠΏΠΎΠ»ΡƒΡ‡Π°Π²Π° Π΄Π°Π½Π½ΠΈ ΠΎΡ‚ Π½Π΅Π³ΠΎ.

Python ΠΌΠΎΠΆΠ΅ Π΄Π° скриС ΠΈΠ·Π²ΠΈΠΊΠ²Π°Π½Π΅Ρ‚ΠΎ, Ρ‚Π°ΠΊΠ° Ρ‡Π΅ крайният ΠΊΠΎΠ΄ Π΄Π° станС ΠΏΠΎ-ΠΊΡ€Π°Ρ‚ΡŠΠΊ. ΠŸΡ€Π΅ΠΏΠΎΡ€ΡŠΡ‡Π²Π°ΠΌΠ΅ Π΄Π° Π³ΠΎ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚Π΅ само Π·Π° отстраняванС Π½Π° ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠΈ. Π‘Π»Π΅Π΄Π²Π°Ρ‰ΠΈΡ‚Π΅ Π΄Π²Π΅ Ρ€Π΅Π΄Π° правят Π°Π±ΡΠΎΠ»ΡŽΡ‚Π½ΠΎ Π΅Π΄Π½ΠΎ ΠΈ ΡΡŠΡ‰ΠΎ: .wrapper_object()dlg_spec.wrapper_object().minimize() # отстраняванС Π½Π° ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠΈ dlg_spec.minimize() # продукция

Има ΠΌΠ½ΠΎΠ³ΠΎ ΠΊΡ€ΠΈΡ‚Π΅Ρ€ΠΈΠΈ Π·Π° Ρ‚ΡŠΡ€ΡΠ΅Π½Π΅ Π·Π° спСцификацията Π½Π° ΠΏΡ€ΠΎΠ·ΠΎΡ€Π΅Ρ†Π°. Π•Ρ‚ΠΎ само няколко ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π°:

Бписък Π½Π° всички възмоТни ΠΊΡ€ΠΈΡ‚Π΅Ρ€ΠΈΠΈ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° Π½Π°ΠΌΠ΅Ρ€ΠΈΡ‚Π΅ Π² докумСнтацията Π½Π° функцията

# ΠΌΠΎΠ³ΡƒΡ‚ ΠΈΠΌΠ΅Ρ‚ΡŒ нСсколько ΡƒΡ€ΠΎΠ²Π½Π΅ΠΉ
app.window(title_re='.* - Notepad$').window(class_name='Edit')

# ΠΌΠΎΠΆΠ½ΠΎ ΠΊΠΎΠΌΠ±ΠΈΠ½ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΊΡ€ΠΈΡ‚Π΅Ρ€ΠΈΠΈ (ΠΊΠ°ΠΊ AND) ΠΈ Π½Π΅ ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡ΠΈΠ²Π°Ρ‚ΡŒΡΡ ΠΎΠ΄Π½ΠΈΠΌ процСссом прилоТСния
dlg = Desktop(backend="uia").Calculator
dlg.window(auto_id='num8Button', control_type='Button')

pywinauto.findwindows.find_elements(…) Python опростява ΡΡŠΠ·Π΄Π°Π²Π°Π½Π΅Ρ‚ΠΎ Π½Π° спСцификации Π½Π° ΠΏΡ€ΠΎΠ·ΠΎΡ€Ρ†ΠΈΡ‚Π΅ ΠΈ Ρ€Π°Π·ΠΏΠΎΠ·Π½Π°Π²Π° Π°Ρ‚Ρ€ΠΈΠ±ΡƒΡ‚ΠΈΡ‚Π΅ Π½Π° ΠΎΠ±Π΅ΠΊΡ‚Π° Π΄ΠΈΠ½Π°ΠΌΠΈΡ‡Π½ΠΎ (Π²ΡŠΡ‚Ρ€Π΅ Π΅ прСзаписан ΠΌΠ΅Ρ‚ΠΎΠ΄ΡŠΡ‚.

Магия Π½Π° Π΄ΠΎΡΡ‚ΡŠΠΏΠ° ΠΏΠΎ Π°Ρ‚Ρ€ΠΈΠ±ΡƒΡ‚ ΠΈ ΠΊΠ»ΡŽΡ‡

__getattribute__ __getattribute__). Π Π°Π·Π±ΠΈΡ€Π° сС, ΠΈΠΌΠ΅Ρ‚ΠΎ Π½Π° Π°Ρ‚Ρ€ΠΈΠ±ΡƒΡ‚Π° ΠΏΠΎΠ΄Π»Π΅ΠΆΠΈ Π½Π° ΡΡŠΡ‰ΠΈΡ‚Π΅ ограничСния, ΠΊΠ°ΠΊΡ‚ΠΎ ΠΈ ΠΈΠΌΠ΅Ρ‚ΠΎ Π½Π° всяка ΠΏΡ€ΠΎΠΌΠ΅Π½Π»ΠΈΠ²Π° (Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° Π²ΠΌΡŠΠΊΠ²Π°Ρ‚Π΅ ΠΏΡ€ΠΎΠ±Π΅Π»ΠΈ, Π·Π°ΠΏΠ΅Ρ‚Π°ΠΉΠΊΠΈ ΠΈΠ»ΠΈ Π΄Ρ€ΡƒΠ³ΠΈ спСциални символи). Π—Π° щастиС, pywinauto ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° Ρ‚Π°ΠΊΠ° нарСчСния Π°Π»Π³ΠΎΡ€ΠΈΡ‚ΡŠΠΌ Π·Π° β€žΠ½Π°ΠΉ-Π΄ΠΎΠ±Ρ€ΠΎ ΡΡŠΠ²ΠΏΠ°Π΄Π΅Π½ΠΈΠ΅β€œ, ΠΊΠΎΠΉΡ‚ΠΎ Π΅ устойчив Π½Π° ΠΏΠ΅Ρ‡Π°Ρ‚Π½ΠΈ Π³Ρ€Π΅ΡˆΠΊΠΈ ΠΈ ΠΌΠ°Π»ΠΊΠΈ Π²Π°Ρ€ΠΈΠ°Ρ†ΠΈΠΈ.

app.UntitledNotepad
# ΡΡŠΡ‰ΠΎΡ‚ΠΎ ΠΊΠ°Ρ‚ΠΎ
app.window(best_match='UntitledNotepad')

Ако всС ΠΏΠ°ΠΊ са Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΈ Unicode строки (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Π·Π° руски Π΅Π·ΠΈΠΊ), ΠΏΡ€ΠΎΠ±Π΅Π»ΠΈΡ‚Π΅ ΠΈ Ρ‚.Π½., ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚Π΅ Π΄ΠΎΡΡ‚ΡŠΠΏ ΠΏΠΎ ΠΊΠ»ΡŽΡ‡ (ΠΊΠ°Ρ‚ΠΎ Ρ‡Π΅ Π»ΠΈ Π΅ ΠΎΠ±ΠΈΠΊΠ½ΠΎΠ²Π΅Π½ Ρ€Π΅Ρ‡Π½ΠΈΠΊ):

app['Untitled - Notepad']
# ΡΡŠΡ‰ΠΎΡ‚ΠΎ ΠΊΠ°Ρ‚ΠΎ
app.window(best_match='Untitled - Notepad')

ΠŸΠ΅Ρ‚ ΠΏΡ€Π°Π²ΠΈΠ»Π° Π·Π° магичСски ΠΈΠΌΠ΅Π½Π°

Как Π΄Π° Ρ€Π°Π·Π±Π΅Ρ€Π΅Ρ‚Π΅ стандартнитС магичСски ΠΈΠΌΠ΅Π½Π°? Π’Π΅Π·ΠΈ, ΠΊΠΎΠΈΡ‚ΠΎ сС присвояват Π½Π° Π΅Π»Π΅ΠΌΠ΅Π½Ρ‚Π° ΠΏΡ€Π΅Π΄ΠΈ Ρ‚ΡŠΡ€ΡΠ΅Π½Π΅Ρ‚ΠΎ. Ако Π·Π°Π΄Π°Π΄Π΅Ρ‚Π΅ ΠΈΠΌΠ΅, ΠΊΠΎΠ΅Ρ‚ΠΎ Π΅ доста Π±Π»ΠΈΠ·ΠΊΠΎ Π΄ΠΎ стандартното, Π·Π½Π°Ρ‡ΠΈ Π΅Π»Π΅ΠΌΠ΅Π½Ρ‚ΡŠΡ‚ Ρ‰Π΅ бъдС Π½Π°ΠΌΠ΅Ρ€Π΅Π½.

  1. По Π·Π°Π³Π»Π°Π²ΠΈΠ΅Ρ‚ΠΎ (тСкст, ΠΈΠΌΠ΅): app.Properties.OK.click()
  2. По тСкста ΠΈ ΠΏΠΎ Ρ‚ΠΈΠΏΠ° Π½Π° Π΅Π»Π΅ΠΌΠ΅Π½Ρ‚Π°: app.Properties.OKButton.click()
  3. По Ρ‚ΠΈΠΏΠ° ΠΈ ΠΏΠΎ Π½ΠΎΠΌΠ΅Ρ€Π°: app.Properties.Button3.click() (ΠΈΠΌΠ΅Π½Π°Ρ‚Π° Button0 ΠΈ Button1 са ΡΠ²ΡŠΡ€Π·Π°Π½ΠΈ с ΠΏΡŠΡ€Π²ΠΈΡ Π½Π°ΠΌΠ΅Ρ€Π΅Π½ Π΅Π»Π΅ΠΌΠ΅Π½Ρ‚, Button2 β€” с втория, ΠΈ Π½Π°Ρ‚Π°Ρ‚ΡŠΠΊ ΠΏΠΎ Ρ€Π΅Π΄Π° β€” Ρ‚ΠΎΠ²Π° Π΅ историчСски установСно)
  4. По статичния тСкст (отляво ΠΈΠ»ΠΈ ΠΎΡ‚Π³ΠΎΡ€Π΅) ΠΈ ΠΏΠΎ Ρ‚ΠΈΠΏΠ°: app.OpenDialog.FileNameEdit.set_text("") (ΠΏΠΎΠ»Π΅Π·Π½ΠΎ Π·Π° Π΅Π»Π΅ΠΌΠ΅Π½Ρ‚ΠΈ с Π΄ΠΈΠ½Π°ΠΌΠΈΡ‡Π΅Π½ тСкст)
  5. По Ρ‚ΠΈΠΏΠ° ΠΈ ΠΏΠΎ тСкста Π²ΡŠΡ‚Ρ€Π΅: app.Properties.TabControlSharing.select("General")

ОбикновСно Π΄Π²Π΅-Ρ‚Ρ€ΠΈ ΠΏΡ€Π°Π²ΠΈΠ»Π° сС ΠΏΡ€ΠΈΠ»Π°Π³Π°Ρ‚ Π΅Π΄Π½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎ, рядко ΠΏΠΎΠ²Π΅Ρ‡Π΅. Π—Π° Π΄Π° ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΈΡ‚Π΅ ΠΊΠ°ΠΊΠ²ΠΈ ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½ΠΈ ΠΈΠΌΠ΅Π½Π° са Π½Π°Π»ΠΈΡ‡Π½ΠΈ Π·Π° всСки Π΅Π»Π΅ΠΌΠ΅Π½Ρ‚, ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚Π΅ ΠΌΠ΅Ρ‚ΠΎΠ΄Π° print_control_identifiers(). Π’ΠΎΠΉ ΠΌΠΎΠΆΠ΅ Π΄Π° ΠΎΡ‚ΠΏΠ΅Ρ‡Π°Ρ‚Π° Π΄ΡŠΡ€Π²ΠΎΡ‚ΠΎ Π½Π° Π΅Π»Π΅ΠΌΠ΅Π½Ρ‚ΠΈΡ‚Π΅ ΠΊΠ°ΠΊΡ‚ΠΎ Π½Π° Π΅ΠΊΡ€Π°Π½Π°, Ρ‚Π°ΠΊΠ° ΠΈ Π² Ρ„Π°ΠΉΠ». Π—Π° всСки Π΅Π»Π΅ΠΌΠ΅Π½Ρ‚ сС ΠΎΡ‚ΠΏΠ΅Ρ‡Π°Ρ‚Π²Π°Ρ‚ Π½Π΅Π³ΠΎΠ²ΠΈΡ‚Π΅ стандартни магичСски ΠΈΠΌΠ΅Π½Π°. Π‘ΡŠΡ‰ΠΎ Ρ‚Π°ΠΊΠ° ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° ΠΊΠΎΠΏΠΈΡ€Π°Ρ‚Π΅ ΠΎΡ‚Ρ‚Π°ΠΌ ΠΏΠΎ-ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π½ΠΈ спСцификации Π½Π° Π΄ΠΎΡ‡Π΅Ρ€Π½ΠΈΡ‚Π΅ Π΅Π»Π΅ΠΌΠ΅Π½Ρ‚ΠΈ. Π Π΅Π·ΡƒΠ»Ρ‚Π°Ρ‚ΡŠΡ‚ Π² скрипта Ρ‰Π΅ ΠΈΠ·Π³Π»Π΅ΠΆΠ΄Π° Ρ‚Π°ΠΊΠ°:

app.Properties.child_window(title="Contains:", auto_id="13087", control_type="Edit")

Π‘Π°ΠΌΠΎΡ‚ΠΎ Π΄ΡŠΡ€Π²ΠΎ Π½Π° Π΅Π»Π΅ΠΌΠ΅Π½Ρ‚ΠΈΡ‚Π΅ β€” ΠΎΠ±ΠΈΠΊΠ½ΠΎΠ²Π΅Π½ΠΎ доста голяма ΠΏΠΎΡ€Π΅Π΄ΠΈΡ†Π°.

>>> app.Properties.print_control_identifiers()

Π˜Π΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ΠΈ Π½Π° ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»:

Π”ΠΈΠ°Π»ΠΎΠ³ - 'Windows NT Properties' (L688, T518, R1065, B1006)
[u'Windows NT PropertiesDialog', u'Dialog', u'Windows NT Properties']
child_window(title="Windows NT Properties", control_type="Window")
   |
   | Π˜Π·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ - '' (L717, T589, R749, B622)
   | [u'', u'0', u'Image1', u'Image0', 'Image', u'1']
   | child_window(auto_id="13057", control_type="Image")
   |
   | Π˜Π·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ - '' (L717, T630, R1035, B632)
   | ['Image2', u'2']
   | child_window(auto_id="13095", control_type="Image")
   |
   | Π Π΅Π΄Π°ΠΊΡ‚ΠΈΡ€Π°Π½Π΅ - 'ИмС Π½Π° ΠΏΠ°ΠΏΠΊΠ°Ρ‚Π°:' (L790, T596, R1036, B619)
   | [u'3', 'Edit', u'Edit1', u'Edit0']
   | child_window(title="Folder name:", auto_id="13156", control_type="Edit")
   |
   | Π‘Ρ‚Π°Ρ‚ΠΈΡ‡Π΅Π½ тСкст - 'Π’ΠΈΠΏ:' (L717, T643, R780, B658)
   | [u'Type:Static', u'Static', u'Static1', u'Static0', u'Type:']
   | child_window(title="Type:", auto_id="13080", control_type="Text")
   |
   | Π Π΅Π΄Π°ΠΊΡ‚ΠΈΡ€Π°Π½Π΅ - 'Π’ΠΈΠΏ:' (L790, T643, R1036, B666)
   | [u'4', 'Edit2', u'Type:Edit']
   | child_window(title="Type:", auto_id="13059", control_type="Edit")
   |
   | Π‘Ρ‚Π°Ρ‚ΠΈΡ‡Π΅Π½ тСкст - 'ΠœΠ΅ΡΡ‚ΠΎΠΏΠΎΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅:' (L717, T669, R780, B684)
   | [u'Location:Static', u'Location:', u'Static2']
   | child_window(title="Location:", auto_id="13089", control_type="Text")
   |
   | Π Π΅Π΄Π°ΠΊΡ‚ΠΈΡ€Π°Π½Π΅ - 'ΠœΠ΅ΡΡ‚ΠΎΠΏΠΎΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅:' (L790, T669, R1036, B692)
   | ['Edit3', u'Location:Edit', u'5']
   | child_window(title="Location:", auto_id="13065", control_type="Edit")
   |
   | Π‘Ρ‚Π°Ρ‚ΠΈΡ‡Π΅Π½ тСкст - 'Π Π°Π·ΠΌΠ΅Ρ€:' (L717, T695, R780, B710)
   | [u'Size:Static', u'Size:', u'Static3']
   | child_window(title="Size:", auto_id="13081", control_type="Text")
   |
   | Π Π΅Π΄Π°ΠΊΡ‚ΠΈΡ€Π°Π½Π΅ - 'Π Π°Π·ΠΌΠ΅Ρ€:' (L790, T695, R1036, B718)
   | ['Edit4', u'6', u'Size:Edit']
   | child_window(title="Size:", auto_id="13064", control_type="Edit")
   |
   | Π‘Ρ‚Π°Ρ‚ΠΈΡ‡Π΅Π½ тСкст - 'Π Π°Π·ΠΌΠ΅Ρ€ Π½Π° диска:' (L717, T721, R780, B736)
   | [u'Size on disk:', u'Size on disk:Static', u'Static4']
   | child_window(title="Size on disk:", auto_id="13107", control_type="Text")
   |
   | Π Π΅Π΄Π°ΠΊΡ‚ΠΈΡ€Π°Π½Π΅ - 'Π Π°Π·ΠΌΠ΅Ρ€ Π½Π° диска:' (L790, T721, R1036, B744)
   | ['Edit5', u'7', u'Size on disk:Edit']
   | child_window(title="Size on disk:", auto_id="13106", control_type="Edit")
   |
   | Π‘Ρ‚Π°Ρ‚ΠΈΡ‡Π΅Π½ тСкст - 'Π‘ΡŠΠ΄ΡŠΡ€ΠΆΠ°:' (L717, T747, R780, B762)
   | [u'Contains:1', u'Contains:0', u'Contains:Static', u'Static5', u'Contains:']
   | child_window(title="Contains:", auto_id="13088", control_type="Text")
   |
   | Π Π΅Π΄Π°ΠΊΡ‚ΠΈΡ€Π°Π½Π΅ - 'Π‘ΡŠΠ΄ΡŠΡ€ΠΆΠ°:' (L790, T747, R1036, B770)
   | [u'8', 'Edit6', u'Contains:Edit']
   | child_window(title="Contains:", auto_id="13087", control_type="Edit")
   |
   | Π˜Π·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ - 'Π‘ΡŠΠ΄ΡŠΡ€ΠΆΠ°:' (L717, T773, R1035, B775)
   | [u'Contains:Image', 'Image3', u'Contains:2']
   | child_window(title="Contains:", auto_id="13096", control_type="Image")
   |
   | Π‘Ρ‚Π°Ρ‚ΠΈΡ‡Π΅Π½ тСкст - 'БъздадСн:' (L717, T786, R780, B801)
   | [u'Created:', u'Created:Static', u'Static6', u'Created:1', u'Created:0']
   | child_window(title="Created:", auto_id="13092", control_type="Text")
   |
   | Π Π΅Π΄Π°ΠΊΡ‚ΠΈΡ€Π°Π½Π΅ - 'БъздадСн:' (L790, T786, R1036, B809)
   | [u'Created:Edit', 'Edit7', u'9']
   | child_window(title="Created:", auto_id="13072", control_type="Edit")
   |
   | Π˜Π·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ - 'БъздадСн:' (L717, T812, R1035, B814)
   | [u'Created:Image', 'Image4', u'Created:2']
   | child_window(title="Created:", auto_id="13097", control_type="Image")
   |
   | Π‘Ρ‚Π°Ρ‚ΠΈΡ‡Π΅Π½ тСкст - 'Атрибути:' (L717, T825, R780, B840)
   | [u'Attributes:Static', u'Static7', u'Attributes:']
   | child_window(title="Attributes:", auto_id="13091", control_type="Text")
   |
   | ЧСкбокс - 'Π‘Π°ΠΌΠΎ Π·Π° Ρ‡Π΅Ρ‚Π΅Π½Π΅ (ΠŸΡ€ΠΈΠ»ΠΎΠΆΠΈΠΌΠΎ само Π·Π° Ρ„Π°ΠΉΠ»ΠΎΠ²Π΅ Π² ΠΏΠ°ΠΏΠΊΠ°Ρ‚Π°)' (L790, T825, R1035, B841)
   | [u'CheckBox0', u'CheckBox1', 'CheckBox', u'Read-only (Only applies to files in folder)CheckBox', u'Read-only (Only applies to files in folder)']
   | child_window(title="Read-only (Only applies to files in folder)", auto_id="13075", control_type="CheckBox")
   |
   | ЧСкбокс - 'Π‘ΠΊΡ€ΠΈΡ‚' (L790, T848, R865, B864)
   | ['CheckBox2', u'HiddenCheckBox', u'Hidden']
   | child_window(title="Hidden", auto_id="13076", control_type="CheckBox")
   |
   | Π‘ΡƒΡ‚ΠΎΠ½ - 'Π Π°Π·ΡˆΠΈΡ€Π΅Π½ΠΈ...' (L930, T845, R1035, B868)
   | [u'Advanced...', u'Advanced...Button', 'Button', u'Button1', u'Button0']
   | child_window(title="Advanced...", auto_id="13154", control_type="Button")
   |
   | Π‘ΡƒΡ‚ΠΎΠ½ - 'ОК' (L814, T968, R889, B991)
   | ['Button2', u'OK', u'OKButton']
   | child_window(title="OK", auto_id="1", control_type="Button")
   |
   | Π‘ΡƒΡ‚ΠΎΠ½ - 'ΠžΡ‚ΠΌΡΠ½Π°' (L895, T968, R970, B991)
   | ['Button3', u'CancelButton', u'Cancel']
   | child_window(title="Cancel", auto_id="2", control_type="Button")
   |
   | Π‘ΡƒΡ‚ΠΎΠ½ - 'ΠŸΡ€ΠΈΠ»Π°Π³Π°Π½Π΅' (L976, T968, R1051, B991)
   | ['Button4', u'ApplyButton', u'Apply']
   | child_window(title="Apply", auto_id="12321", control_type="Button")
   |
   | TabControl - '' (L702, T556, R1051, B962)
   | [u'10', u'TabControlSharing', u'TabControlPrevious Versions', u'TabControlSecurity', u'TabControl', u'TabControlCustomize']
   | child_window(auto_id="12320", control_type="Tab")
   |    |
   |    | TabItem - 'ΠžΠ±Ρ‰ΠΈ' (L704, T558, R753, B576)
   |    | [u'GeneralTabItem', 'TabItem', u'General', u'TabItem0', u'TabItem1']
   |    | child_window(title="General", control_type="TabItem")
   |    |
   |    | TabItem - 'БподСлянС' (L753, T558, R801, B576)
   |    | [u'Sharing', u'SharingTabItem', 'TabItem2']
   |    | child_window(title="Sharing", control_type="TabItem")
   |    |
   |    | TabItem - 'Бигурност' (L801, T558, R851, B576)
   |    | [u'Security', 'TabItem3', u'SecurityTabItem']
   |    | child_window(title="Security", control_type="TabItem")
   |    |
   |    | TabItem - 'ΠŸΡ€Π΅Π΄ΠΈΡˆΠ½ΠΈ вСрсии' (L851, T558, R947, B576)
   |    | [u'Previous VersionsTabItem', u'Previous Versions', 'TabItem4']
   |    | child_window(title="Previous Versions", control_type="TabItem")
   |    |
   |    | TabItem - 'ΠŸΠ΅Ρ€ΡΠΎΠ½Π°Π»ΠΈΠ·ΠΈΡ€Π°Π½Π΅' (L947, T558, R1007, B576)
   |    | [u'CustomizeTabItem', 'TabItem5', u'Customize']
   |    | child_window(title="Customize", control_type="TabItem")
   |
   | TitleBar - 'Няма' (L712, T521, R1057, B549)
   | ['TitleBar', u'11']
   |    |
   |    | МСню - 'БистСма' (L696, T526, R718, B548)
   |    | [u'System0', u'System', u'System1', u'Menu', u'SystemMenu']
   |    | child_window(title="System", auto_id="MenuBar", control_type="MenuBar")
   |    |    |
   |    |    | MenuItem - 'БистСма' (L696, T526, R718, B548)
   |    |    | [u'System2', u'MenuItem', u'SystemMenuItem']
   |    |    | child_window(title="System", control_type="MenuItem")
   |    |
   |    | Π‘ΡƒΡ‚ΠΎΠ½ - 'Π—Π°Ρ‚Π²ΠΎΡ€ΠΈ' (L1024, T519, R1058, B549)
   |    | [u'CloseButton', u'Close', 'Button5']
   |    | child_window(title="Close", control_type="Button")

Π’ някои случаи ΠΏΠ΅Ρ‡Π°Ρ‚Π°Π½Π΅Ρ‚ΠΎ Π½Π° цялото Π΄ΡŠΡ€Π²ΠΎ ΠΌΠΎΠΆΠ΅ Π΄Π° Π·Π°Π±Π°Π²ΠΈ производитСлността (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Π² iTunes Π½Π° Π΅Π΄Π½Π° Π²ΠΊΠ»Π°Π΄ΠΊΠ° с Ρ†Π΅Π»ΠΈ Ρ‚Ρ€ΠΈ хиляди Π΅Π»Π΅ΠΌΠ΅Π½Ρ‚Π°!), Π½ΠΎ ΠΌΠΎΠΆΠ΅ Π΄Π° сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚ΡŠΡ€ΡŠΡ‚ depth (Π΄ΡŠΠ»Π±ΠΎΡ‡ΠΈΠ½Π°): depth=1 β€” самият Π΅Π»Π΅ΠΌΠ΅Π½Ρ‚, depth=2 β€” само нСпосрСдствСнитС Π΄Π΅Ρ†Π° ΠΈ Ρ‚Π°ΠΊΠ° Π½Π°Ρ‚Π°Ρ‚ΡŠΠΊ. МоТС Π΄Π° сС Π·Π°Π΄Π°Π²Π° ΠΈ Π² спСцификациитС ΠΏΡ€ΠΈ създаванС Π½Π° child_window.

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ΠΈ

ΠŸΠΎΡΡ‚ΠΎΡΠ½Π½ΠΎ допълвамС списъка с ΠΏΡ€ΠΈΠΌΠ΅Ρ€ΠΈ Π² Ρ…Ρ€Π°Π½ΠΈΠ»ΠΈΡ‰Π΅Ρ‚ΠΎ. ΠžΡ‚ послСднитС, трябва Π΄Π° спомСна автоматизацията Π½Π° мрСТовия Π°Π½Π°Π»ΠΈΠ·Π°Ρ‚ΠΎΡ€ WireShark (Ρ‚ΠΎΠ²Π° Π΅ Π΄ΠΎΠ±ΡŠΡ€ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Π·Π° ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ Π½Π° Qt5; Π²ΡŠΠΏΡ€Π΅ΠΊΠΈ Ρ‡Π΅ Ρ‚Π°Π·ΠΈ Π·Π°Π΄Π°Ρ‡Π° ΠΌΠΎΠΆΠ΅ Π΄Π° сС Ρ€Π΅ΡˆΠ°Π²Π° ΠΈ Π±Π΅Π· Π³Ρ€Π°Ρ„ΠΈΡ‡Π΅Π½ интСрфСйс, Ρ‚ΡŠΠΉ ΠΊΠ°Ρ‚ΠΎ ΠΈΠΌΠ° scapy.Sniffer ΠΎΡ‚ Python ΠΏΠ°ΠΊΠ΅Ρ‚Π° scapy). Има ΠΈ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Π·Π° автоматизация Π½Π° MS Paint с нСговия Ribbon инструмСнтариум.

ΠžΡ‰Π΅ Π΅Π΄ΠΈΠ½ ΠΎΡ‚Π»ΠΈΡ‡Π΅Π½ ΠΏΡ€ΠΈΠΌΠ΅Ρ€, написан ΠΎΡ‚ моя студСнт: плъзганС Π½Π° Ρ„Π°ΠΉΠ» ΠΎΡ‚ explorer.exe Π½Π° Chrome страница Π·Π° Google Drive (Ρ‚ΠΎΠΉ Ρ‰Π΅ ΠΏΡ€Π΅ΠΌΠΈΠ½Π΅ Π² основното Ρ…Ρ€Π°Π½ΠΈΠ»ΠΈΡ‰Π΅ ΠΏΠΎ-късно).

И, Ρ€Π°Π·Π±ΠΈΡ€Π° сС, ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Π·Π° Π°Π±ΠΎΠ½Π°ΠΌΠ΅Π½Ρ‚ Π·Π° ΡΡŠΠ±ΠΈΡ‚ΠΈΡ ΠΎΡ‚ ΠΊΠ»Π°Π²ΠΈΠ°Ρ‚ΡƒΡ€Π°Ρ‚Π° (Π³ΠΎΡ€Π΅Ρ‰ΠΈ клавиши) ΠΈ ΠΌΠΈΡˆΠΊΠ°Ρ‚Π°:
hook_and_listen.py.

Благодарности

ΠžΡ‚Π΄Π΅Π»Π½ΠΎ благодаря Π½Π° Ρ‚Π΅Π·ΠΈ, ΠΊΠΎΠΈΡ‚ΠΎ постоянно ΠΏΠΎΠΌΠ°Π³Π°Ρ‚ Π·Π° Ρ€Π°Π·Π²ΠΈΡ‚ΠΈΠ΅Ρ‚ΠΎ Π½Π° ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π°. Π—Π° ΠΌΠ΅Π½ ΠΈ Π’Π°Π»Π΅Π½Ρ‚ΠΈΠ½Π° Ρ‚ΠΎΠ²Π° Π΅ постоянно Ρ…ΠΎΠ±ΠΈ. Π”Π²Π°ΠΌΠ° ΠΎΡ‚ ΠΌΠΎΠΈΡ‚Π΅ студСнти ΠΎΡ‚ ННГУ наскоро Π·Π°Ρ‰ΠΈΡ‚ΠΈΡ…Π° Π±Π°ΠΊΠ°Π»Π°Π²ΡŠΡ€ΡΠΊΠΈΡ‚Π΅ си стСпСни ΠΏΠΎ Ρ‚Π°Π·ΠΈ Ρ‚Π΅ΠΌΠ°. ΠΠ»Π΅ΠΊΡΠ°Π½Π΄ΡŠΡ€ Π½Π°ΠΏΡ€Π°Π²ΠΈ голям принос Π² ΠΏΠΎΠ΄Π΄Ρ€ΡŠΠΆΠΊΠ°Ρ‚Π° Π½Π° MS UI Automation ΠΈ наскоро Π·Π°ΠΏΠΎΡ‡Π½Π° Π΄Π° Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Π²Π° Π°Π²Ρ‚ΠΎΠΌΠ°Ρ‚ΠΈΡ‡Π΅Π½ Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€ Π½Π° ΠΊΠΎΠ΄ ΠΏΠΎ ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏΠ° β€žΠ·Π°ΠΏΠΈΡ-Π²ΡŠΠ·ΠΏΡ€ΠΎΠΈΠ·Π²Π΅ΠΆΠ΄Π°Π½Π΅β€œ Π½Π° основата Π½Π° тСкстови свойства (Ρ‚ΠΎΠ²Π° Π΅ Π½Π°ΠΉ-слоТната функция), засСга само Π·Π° Π±Π΅ΠΊΠ΅Π½Π΄Π° β€žuiaβ€œ. Иван Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Π²Π° Π½ΠΎΠ² Π±Π΅ΠΊΠ΅Π½Π΄ ΠΏΠΎΠ΄ Linux Π½Π° основата Π½Π° AT-SPI (ΠΌΠΎΠ΄ΡƒΠ»ΠΈΡ‚Π΅ mouse ΠΈ keyboard Π½Π° Π±Π°Π·Π° python-xlib β€” Π²Π΅Ρ‡Π΅ са Π² вСрсии 0.6.x).

Въй ΠΊΠ°Ρ‚ΠΎ ΠΎΡ‚ доста Π²Ρ€Π΅ΠΌΠ΅ ΠΏΡ€Π΅ΠΏΠΎΠ΄Π°Π²Π°ΠΌ спСциалСн курс ΠΏΠΎ автоматизация Π½Π° Python, част ΠΎΡ‚ ΠΌΠ°Π³ΠΈΡΡ‚ΡŠΡ€ΡΠΊΠΈΡ‚Π΅ студСнти ΠΈΠ·ΠΏΡŠΠ»Π½ΡΠ²Π°Ρ‚ домашни задания, Ρ€Π΅Π°Π»ΠΈΠ·ΠΈΡ€Π°ΠΉΠΊΠΈ ΠΌΠ°Π»ΠΊΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΈΠ»ΠΈ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ΠΈ Π·Π° автоматизация. Някои ΠΊΠ»ΡŽΡ‡ΠΎΠ²ΠΈ Π½Π΅Ρ‰Π° Π² Π΅Ρ‚Π°ΠΏΠ° Π½Π° изслСдвания ΡΡŠΡ‰ΠΎ бяха ΠΎΡ‚ΠΊΡ€ΠΈΡ‚ΠΈ ΠΎΡ‚ студСнти. Π’ΡŠΠΏΡ€Π΅ΠΊΠΈ Ρ‡Π΅ понякога трябва Π΄Π° слСдя качСството Π½Π° ΠΊΠΎΠ΄Π°. Π—Π° Ρ‚ΠΎΠ²Π° ΠΌΠ½ΠΎΠ³ΠΎ ΠΏΠΎΠΌΠ°Π³Π°Ρ‚ статичнитС Π°Π½Π°Π»ΠΈΠ·Π°Ρ‚ΠΎΡ€ΠΈ (QuantifiedCode, Codacy ΠΈ Landscape) ΠΈ Π°Π²Ρ‚ΠΎΠΌΠ°Ρ‚ΠΈΡ‡Π½ΠΈΡ‚Π΅ тСстовС Π² ΠΎΠ±Π»Π°ΠΊΠ° (услугата AppVeyor) с ΠΏΠΎΠΊΡ€ΠΈΡ‚ΠΈΠ΅ Π½Π° ΠΊΠΎΠ΄Π° ΠΎΠΊΠΎΠ»ΠΎ 95%.

Π‘ΡŠΡ‰ΠΎ Ρ‚Π°ΠΊΠ° благодаря Π½Π° всички, ΠΊΠΎΠΈΡ‚ΠΎ оставят ΠΎΡ‚Π·ΠΈΠ²ΠΈ, ΡΡŠΠ·Π΄Π°Π²Π°Ρ‚ бъговС ΠΈ ΠΈΠ·ΠΏΡ€Π°Ρ‰Π°Ρ‚ ΠΏΡƒΠ» рСквСсти!

Π”ΠΎΠΏΡŠΠ»Π½ΠΈΡ‚Π΅Π»Π½ΠΈ рСсурси

Π—Π° Π²ΡŠΠΏΡ€ΠΎΡΠΈΡ‚Π΅ слСдим ΠΏΠΎ Ρ‚Π΅Π³Π° Π½Π° StackOverflow (Π½Π΅ΠΎΡ‚Π΄Π°Π²Π½Π° сС появи Ρ‚Π΅Π³ Π² руската вСрсия Π½Π° SO) ΠΈ ΠΏΠΎ ΠΊΠ»ΡŽΡ‡ΠΎΠ²Π°Ρ‚Π° Π΄ΡƒΠΌΠ° Π½Π° ВостСра. Има рускоязичСн Ρ‡Π°Ρ‚ Π² Gitter’С.

ВсСки мСсСц обновявамС Ρ€Π΅ΠΉΡ‚ΠΈΠ½Π³Π° Π½Π° open-source Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ Π·Π° тСстиранС Π½Π° GUI. По количСство Π·Π²Π΅Π·Π΄ΠΈ Π² GitHub, ΡΠ°ΠΌΠΎΡŠΡΡ‚Π²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΈΡ‚Π΅ ΠΈΠΌ растат само Autohotkey (Ρ‚Π΅ ΠΈΠΌΠ°Ρ‚ ΠΌΠ½ΠΎΠ³ΠΎ голяма общност ΠΈ дълга история) ΠΈ PyAutoGUI (Π² Π·Π½Π°Ρ‡ΠΈΡ‚Π΅Π»Π½Π° стСпСн Π±Π»Π°Π³ΠΎΠ΄Π°Ρ€Π΅Π½ΠΈΠ΅ Π½Π° популярността Π½Π° ΠΊΠ½ΠΈΠ³ΠΈΡ‚Π΅ Π½Π° нСйния Π°Π²Ρ‚ΠΎΡ€ Al Sweigart: Β«Automate the Boring Stuff with PythonΒ» ΠΈ Π΄Ρ€ΡƒΠ³ΠΈ).

Π˜Π·Ρ‚ΠΎΡ‡Π½ΠΈΠΊ: habr.com

ΠšΡƒΠΏΠ΅Ρ‚Π΅ Π½Π°Π΄Π΅ΠΆΠ΄Π΅Π½ хостинг Π·Π° сайтовС със Π·Π°Ρ‰ΠΈΡ‚Π° ΠΎΡ‚ DDoS, VPS ΠΈ VDS ΡΡŠΡ€Π²ΡŠΡ€ΠΈ πŸ”₯ ΠšΡƒΠΏΠ΅Ρ‚Π΅ Π½Π°Π΄Π΅ΠΆΠ΄Π΅Π½ хостинг Π·Π° сайтовС със Π·Π°Ρ‰ΠΈΡ‚Π° ΠΎΡ‚ DDoS, VPS ΠΈ VDS ΡΡŠΡ€Π²ΡŠΡ€ΠΈ | ProHoster