pywinauto 自动化入门

发布时间 2023-07-02 21:58:22作者: 心随所遇
# 第一步 实例化要操作的进程:得到的 Application 对象
# 第二步 选择窗口 :app.window(筛选条件) 得到的窗口是 WindowSpecification对象
# 第三步:基于 WindowSpecification 对象使用其方法再往下查找,定位到具体的控件
# 第四步:使用控件执行我们需要的控制操作

# 获取应用对象两种方式
# 以直接打开方式
# app = Application(backend='uia').start('D:\Program Files (x86)\Tencent\WeChat\WeChat.exe')
# 以连接方式
# app = Application(backend='uia').connect(path = r"D:\Program Files (x86)\Tencent\WeChat\WeChat.exe")
# app = Application(backend='uia').connect(process = pid)
# app = Application(backend='uia').connect(handle = 0x010f0c) # 句柄
# app = Application(backend='uia').connect(class_name="Chrome_WidgetWin_1", control_type="Window") # 参数组合

# Application 对象常用方法属性
# app.process 进程 id 属性
# app.kill(soft=False) # 强制关闭
# app.cpu_usage() # 返回指定秒数期间的CPU使用率百分比
# app.wait_cpu_usage_lower(threshold=2.5, timeout=None, usage_interval=None) # 等待进程CPU使用率百分比小于指定的阈值threshold
# app.is_process_running() 当前进程是否运行中
# app.is_process_running() 当前进程是否运行中
# app.top_window() 返回顶层窗口对象, app 特有
# pywinauto.application.process_module(app.process) 打印进程模块名

# 父级控件对象查找子控件的方法
# parent.window(**keyword)
# parent.windows(**keyword)
# parent.children(**keyword) #直系
# parent.child_window(**keyword) #能隔代
# parent.parent()
# parent.iter_children(**keyword)
# parent.descendants(**keyword) #查找所有后代中满足的

# 查找条件(keyword)关键字
# title_re 标题正则匹配
# class_name_re 类名正则匹配
# best_match 标题与此类似的元素
# top_level_only=True 仅限顶级元素(默认值=True)
# handle 要返回的元素的句柄
# ctrl_index 要返回的子元素的索引
# found_index 要返回的已过滤子元素的索引
# predicate_func 用户为自定义元素验证提供了钩子
# active_only=False 仅限活动元素
# control_id 具有此控件ID的元素
# control_type 具有此控件类型的元素(字符串;用于UIAutomation元素)
# auto_id 具有此自动化ID的元素(用于UIAutomation元素)
# framework_id 具有此框架ID的元素(用于UIAutomation元素)
# backend 搜索时使用的后端名称(默认=None表示当前活动后端)

# 关键字对应 inspect.exe(尽量找最新版本) 工具查看到的属性
# title_re = Name
# class_name_re = ClassName
# process = ProcessId
# auto_id = AutomationId
# handle = NativeWindowHandle 例如:handle=0x1038C
# framework_id = FrameworkId
# control_type = LocalizedControlType 不是中文的,control_type 值有 Window Pane MenuBar Button Image Edit MenuItem

# 支持窗口模式的控件对象方法
# control.close()
# control.minimize()
# control.maximize()
# control.restore() # 恢复
# control.get_show_state() # 正常0,最大化1,最小化2
# control.exists(timeout=None, retry_interval=None) # retry_interval:timeout内重试时间
# control.wait(state, timeout=None, retry_interval=None) #状态:'exists' 'visible' 'enabled' 'ready' 'active'
# control.wait_not(state, timeout=None, retry_interval=None)


# 控件的常用属性和操作
# control.window_text()
# control.class_name()
# control.children_texts()
# control.element_info.name
# control.element_info.class_name
# control.element_info.control_type

# control.is_child(parent)
# control.legacy_properties().get('Value') # 可以获取inspect界面LegacyIAccessible开头的一系列字段
# control.is_dialog()
# control.draw_outline(colour='red') # 给控件画轮廓线
# control.dump_tree(depth=None, filename=None) # 打印窗体内所有元素控件
# control.scroll(direction, amount, count=1,) # direction :"up", "down", "left", "right" 方向 # amount:"line" or "page" 行或页 # count:int 滚动次数
# control.capture_as_image().save(path) # 获取控件的 PIL image对象并保存
# control.rectangle() # 控件上下左右坐标
# control.exists()
# control.wrapper_object()

# 控件里的鼠标键盘操作
# control.click_input()
# control.right_click_input()
# control.type_keys(keys, pause = None, with_spaces = False,) # pause:输入间隔 with_spaces:是否保留空格
# control.double_click_input(button ="left", coords = (None, None)) # 左键双击
# control.press_mouse_input(coords = (None, None)) # 指定坐标按下左键,不传坐标默认左上角
# control.release_mouse_input(coords = (None, None)) # 指定坐标释放左键,不传坐标默认左上角
# control.move_mouse_input(coords=(0, 0)) # 将鼠标移动到指定坐标,不传坐标默认左上角
# control.drag_mouse_input(dst=(0, 0)) # 拖拽到指定坐标位置

# 自由鼠标键盘操作
# mouse.move(coords=(x, y))
# mouse.click(button='left', coords=(40, 40))
# mouse.double_click(button='left', coords=(140, 40))
# mouse.press(button='left', coords=(140, 40))
# mouse.release(button='left', coords=(300, 40))
# mouse.right_click(coords=(400, 400))
# mouse.wheel_click(coords=(400, 400)) # 中键单击
# mouse.scroll(coords=(1200,300),wheel_dist=-3) #滚轮滑动,正数往上,负数往下

# 按键名称
# {ESC} {F1} {SPACE} {BKSP} {DELETE} {HELP} {NUMLOCK} {TAB} {END} {BACK} {SCROLLLOCK} {VK_SCROLL} {VK_MULTIPLY} {VK_HOME} {VK_PAUSE} {VK_LSHIFT}
# {UP} {DOWN} {LEFT} {RIGHT} {VK_LSHIFT}, {VK_PAUSE}, {VK_MODECHANGE},
# {BACK}, {VK_HOME}, {VK_HANGEUL}, {VK_KANJI}, {VK_RIGHT}, {BS}, {HOME}, {VK_F4}, {VK_ACCEPT}, {VK_F18}, {VK_SNAPSHOT},
# {VK_PA1}, {VK_NONAME}, {VK_LCONTROL}, {ZOOM}, {VK_ATTN}, {VK_UP}, {NUMLOCK}, {VK_APPS}, {PGUP}, {VK_CONTROL},
# {VK_LEFT}, {PRTSC}, {VK_NUMPAD4}, {CAPSLOCK}, {VK_CONVERT}, {VK_PROCESSKEY},
# {ENTER}, {VK_SEPARATOR}, {VK_RWIN}, {VK_LMENU}, {VK_NEXT}, {VK_ADD}, {VK_RCONTROL},
# {VK_RETURN}, {BREAK}, {VK_NUMPAD9}, {VK_NUMPAD8}, {RWIN}, {VK_KANA},
# {PGDN}, {VK_NUMPAD3}, {VK_NUMPAD1}, {VK_NUMPAD0}, {VK_NUMPAD7},
# {VK_NUMPAD6}, {VK_NUMPAD5}, {VK_PRIOR}, {VK_SUBTRACT}, {HELP},
# {VK_PRINT}, {VK_BACK}, {CAP}, {VK_RBUTTON}, {VK_RSHIFT}, {VK_LWIN}, 
# {VK_HELP}, {VK_NONCONVERT}, {BACKSPACE}, {VK_SELECT}, {VK_TAB}, {VK_HANJA},
# {VK_NUMPAD2}, {INSERT}, {VK_DECIMAL}, {VK_FINAL}, {VK_EXSEL},
# {RMENU}, {VK_F3}, {VK_F2}, {VK_F1}, {VK_F7}, {VK_F6}, {VK_F5}, {VK_CRSEL},
# {VK_SHIFT}, {VK_EREOF}, {VK_CANCEL}, {VK_DELETE}, {VK_HANGUL}, {VK_MBUTTON},
# {VK_NUMLOCK}, {VK_CLEAR}, , {VK_MENU}, {VK_INSERT},
# {VK_CAPITAL}, {VK_LBUTTON}, {VK_OEM_CLEAR}, {VK_ESCAPE}, {VK_DIVIDE}, {INS}, {VK_JUNJA},
# {VK_EXECUTE}, {VK_PLAY}, {VK_RMENU}, {LWIN},

# 控制键别名:
# {VK_CONTROL}: ^
# {VK_SHIFT} : +
# {VK_MENU} (Alt键) : %

# keyboard.send_keys('^a^c') # Ctrl + A 和 Ctrl + C
# keyboard.send_keys('+{INS}') # Shift + Ins 从剪贴板插入
# keyboard.send_keys('%{F4}') # Alt + F4
# keyboard.send_keys(' {ENTER 2}') # 表示按两次Enter
# keyboard.send_keys("{VK_SHIFT down}" "pywinauto" "{VK_SHIFT up}") # 按下 shift 输入字符串,再释放 shift
# keyboard.send_keys("{h down}" "{e down}" "{h up}" "{e up}" "llo") # to type hello
# keyboard.send_keys('{^}a{^}c{%}') #使用花括号来转义 ^ 键入字符串 "^a^c%"
# keyboard.send_keys('{{}ENTER{}}') #使用花括号来转义{ 和 } 两个符号
 
 
教程就这么多,如果感觉能理解,下面我们上代码吧。
安装扩展包
pip install pywinauto pyautogui

 

入门代码,以打开 edge 浏览器为例

from pywinauto import Application
from pywinauto.application import process_module

app = Application(backend='uia').start(r"C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe")

# 也可以用连接的方式:
# app = Application(backend='uia').connect(class_name="Chrome_WidgetWin_1", framework_id="Win32", control_type="Window")
# app = Application(backend='uia').connect(process=pid) # 这个 pid 可能不好查, 进程管理器能看到的好几个进程

print(app.is_process_running())
print(process_module(app.process))
print(app.top_window())
app.top_window().dump_tree()
 
运行结果如下: 浏览器是打开了,不过代码居然报错了,哈哈。不要慌,这段代码写的就是打印状态,所以很容易排错。
 
意思就是一打开,进程就退出了。原因是我在边写博客别测试,所以浏览器是已经打开的。如果edge 已经启动,那么再启动,就好像进程一启动传个话,就退出了,也就造成报错,关掉重试就好了。