goroumaru41gou

遊んでいる中でインプットした内容をアウトプットする場

pywinautoハマったところ

pythonのアプリケーションからwindows上のGUIを自動化するpywinautoライブラリを利用した際に、ハマった点を備忘録とする。

取り扱うもの

ハマった点

  1. window上で操作したいItemが分かり難い

  2. 操作方法が分かり難い

どのように操作するのか?

例えば、pythonからPDFファイルのプリンタ設定を操作したいとき、 印刷ダイアログを開き、詳細設定ボタンを押下して詳細画面を開いてから、各種設定を実行する。

このとき、詳細設定画面には、様々なアイテム(テキスト・ボタン・チェックボックスなど)が存在するため、それらを識別して操作する必要がある。

pywinautoを利用すると、自動的にそれらを識別してくれるが、どのようなデータ構造で識別されているか知る必要がある。

pywinautoでデータ構造表示する

操作対象であるウィンドウを"window"オブジェクトすると、以下コードで表示できる。

print(window.dump_tree())

//
// 表示結果
//

Dialog - '印刷'    (L76, T16, R615, B493)
['印刷Dialog', 'Dialog', '印刷']
child_window(title="印刷", class_name="#32770")
   | 
 ------------------------ 省略 ------------------------
   | GroupBox - ''    (L380, T295, R587, B432)
   | ['ページ範囲GroupBox2', 'GroupBox4']
   | child_window(class_name="Button")
   | 
   | Static - '部数(&C):'    (L389, T319, R496, B338)
   | ['部数(&C):', '部数(&C):Static', 'Static8']
   | child_window(title="部数(&C):", class_name="Static")
   | 
   | Edit - '1'    (L504, T316, R536, B339)
   | ['Edit5', '部数(&C):Edit']
   | child_window(title="1", class_name="Edit")
   | 
   | CheckBox - '部単位で印刷(&O)'    (L393, T359, R509, B378)
   | ['部単位で印刷(&O)CheckBox', '部単位で印刷(&O)', 'CheckBox2']
   | child_window(title="部単位で印刷(&O)", class_name="Button")
   | 
   | Static - ''    (L463, T379, R580, B418)
   | ['Static9', '部単位で印刷(&O)Static']
   | child_window(class_name="Static")
   | 
   | UpDown - ''    (L534, T316, R552, B339)
   | ['部数(&C):UpDown', 'UpDown']
   | child_window(class_name="msctls_updown32")
   | 
   | Button - '印刷(&P)'    (L329, T456, R417, B482)
   | ['印刷(&P)Button', '印刷(&P)', 'Button3']
   | child_window(title="印刷(&P)", class_name="Button")
   | 
   | Button - 'キャンセル'    (L424, T456, R512, B482)
   | ['キャンセル', 'キャンセルButton', 'Button4']
   | child_window(title="キャンセル", class_name="Button")
   | 
   | Button - '適用(&A)'    (L518, T456, R606, B482)
   | ['適用(&A)Button', 'Button5', '適用(&A)']
   | child_window(title="適用(&A)", class_name="Button")
   | 
   | Button - 'ヘルプ'    (L613, T456, R701, B482)
   | ['ヘルプ', 'Button6', 'ヘルプButton']
   | child_window(title="ヘルプ", class_name="Button")
   | 
   | TabControl - ''    (L86, T50, R605, B449)
   | ['状態:TabControl', 'TabControl全般', 'TabControl']
   | child_window(class_name="SysTabControl32")

構造の操作方法

例えば、印刷部数を変更したいとき、テキストボックスへ部数を入力する。

このとき、以下で表示されるアイテムを操作する。

//
// 表示結果(抜粋)
//

   | Edit - '1'    (L504, T316, R536, B339)
   | ['Edit5', '部数(&C):Edit']
   | child_window(title="1", class_name="Edit")
  • 部数1と入力したいとき

    window["部数(&C):Edit"].set_edit_text("1")

    これは'部数(&C):Edit'をKeyとしてアイテムへアクセスし、メソッド(set_edit_text()など)でアイテムを操作している。


仮に、ほかの表示内容でアクセスを試みると、エラーとなる場合がある。

これは、EditButton1は、固有な名称でないか、可変となる名称であるためで、 それらをKeyとして利用することは、避けた方がよい。

参考