WindowsアプリをPythonから操作できる pywinauto を使って、Windows標準アプリであるメモ帳の操作を自動化してみます。
今回は以下の操作をPythonから実行します。
windows11のメモ帳を使用しています。
- メモ帳を起動
- 設定画面を開く
- フォント設定を展開
- フォントを「メイリオ」に変更
- テーマ設定を展開
- ダークテーマを選択
参考
- https://qiita.com/Linux_box/items/3222b52814df61aebef0
- https://qiita.com/KWS_0901/items/76b47a11cc13dffb4a18
サンプルコード
from pywinauto import Desktop
import subprocess
import time
subprocess.Popen(r'C:\\WINDOWS\\system32\\notepad.exe', shell=True)
time.sleep(5)
app = Desktop(backend="uia")
for win in app.windows():
print(win.texts())
root_win = app['無題 - メモ帳']
root_win["設定"].click()
font_elm = root_win.child_window(title="フォント", auto_id="InternalExpander", control_type="Button")
font_elm.click_input()
family_box = root_win.child_window(title="ファミリ", auto_id="FontFamilyComboBox", control_type="ComboBox", found_index=0)
# 展開して中身が見える状態にする
family_box.expand()
# "ListItem"を指定
family_item = family_box.child_window(title="メイリオ", control_type="ListItem")
# "ListItem"を選択
family_item.select()
thema_elm = root_win.child_window(title="アプリのテーマ", auto_id="InternalExpander", control_type="Button")
thema_elm.click_input()
thema_radio = root_win.child_window(title="ダーク", auto_id="DarkButton", control_type="RadioButton")
thema_radio.select()
child_window()とは?
child_window()は操作対象となるUI部品を指定するためのメソッドです。
例えば以下の場合、
root_win.child_window(
title="ダーク",
auto_id="DarkButton",
control_type="RadioButton"
)
以下の情報を利用して対象の部品を検索しています。
| 指定項目 | 意味 |
|---|---|
| title | 表示されている名前 |
| auto_id | UI Automationで割り当てられたID |
| control_type | ボタンやリストなどの種類 |
取得したUI要素に対して操作を実行します。
例:
.click_input()
クリック
.expand()
展開
.select()
選択
というように、
要素を取得 → 操作を実行
という流れがpywinautoの基本になります。
UI要素の調べ方
pywinautoで自動操作する場合、最初に対象となるUI要素を調べる必要があります。
その時に使用するのが、
root_win.print_control_identifiers()
です。
実行すると、現在表示されている画面のUI構造が一覧表示されます。
例:
Dialog - 'タイトルなし - メモ帳'
Pane
Document
TabControl
ListBox
TabItem
この中から操作したい要素を探し、
root_win.child_window(...)
に指定します。
作成手順
最初は操作を行わず、UI要素の確認だけを行います。
from pywinauto import Desktop
import subprocess
import time
subprocess.Popen(r'C:\\WINDOWS\\system32\\notepad.exe', shell=True)
time.sleep(5)
app = Desktop(backend="uia")
for win in app.windows():
print(win.texts())
root_win = app['無題 - メモ帳']
root_win.print_control_identifiers()
実行すると、現在表示されているメモ帳のUI構造が表示されます。
表示された一覧から目的の要素を探し、
root_win.child_window(...)
を書き加えて操作対象を指定します。
ハマったポイント
ComboBoxが複数見つかる
フォント選択部分で以下のコードを実行すると、
family_box = root_win.child_window(
title="ファミリ",
auto_id="FontFamilyComboBox",
control_type="ComboBox"
)
エラーになりました。
原因は条件に一致するComboBoxが複数存在したためです。
そこで、
found_index=0
を追加しました。
family_box = root_win.child_window(
title="ファミリ",
auto_id="FontFamilyComboBox",
control_type="ComboBox",
found_index=0
)
これで正常に動作しました。
ただし、環境によっては
found_index=1
が正しい場合もあります。
click()とclick_input()の違い
pywinautoにはクリック操作として、
.click()
と
.click_input()
があります。
今回の環境では、
.click()
では正常に動作しませんでした。
そのため、
.click_input()
を使用しました。
違いとしては、
| メソッド | 特徴 |
|---|---|
| click() | UI Automation経由で操作 |
| click_input() | 実際のマウス入力をシミュレート |
となります。
UIによってはclick()で反応しない場合があるため、その場合はclick_input()を試すと解決することがあります。
注意点
WindowsアプリはアップデートなどによってUI構造が変化する場合があります。
その場合、以前動いていたコードでも、
- title
- auto_id
- control_type
などが変わり動作しなくなることがあります。
動作しなくなった場合は、まず
root_win.print_control_identifiers()
で現在のUI構造を確認すると原因を特定しやすくなります。
まとめ
pywinautoでWindowsアプリを自動操作する基本的な流れは、
- アプリを起動
-
print_control_identifiers()でUI要素を確認 -
child_window()で操作対象を取得 -
click_input()やselect()などで操作
になります。
GUI操作を自動化できるため、定型作業のRPA化やテスト自動化などに活用できます。