#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ 快速窗口控件分析器 - 简化版 专门用于快速分析应用程序控件结构 """ import time import sys from pywinauto import Application def quick_analyze(app_path): """快速分析指定应用的窗口控件""" print(f"🔗 连接应用程序: {app_path}") # 特殊处理kiro.exe - 连接到安装界面或应用程序进程 if "kiro.exe" in app_path.lower(): print("🔍 检测到kiro.exe,尝试连接进程...") # 扩展的连接方法:支持安装程序和已安装的应用程序 connection_attempts = [ # 安装程序连接方法(保留原有功能) lambda: Application(backend="uia").connect(title="安装", timeout=5), lambda: Application(backend="win32").connect(title="安装", timeout=5), lambda: Application(backend="uia").connect(title="安装-Kiro (User)", timeout=5), lambda: Application(backend="win32").connect(title="安装-Kiro (User)", timeout=5), lambda: Application(backend="uia").connect(title_re=".*安装.*", timeout=5), lambda: Application(backend="win32").connect(title_re=".*安装.*", timeout=5), lambda: Application(backend="uia").connect(title_re=".*[Ss]etup.*", timeout=5), lambda: Application(backend="win32").connect(title_re=".*[Ss]etup.*", timeout=5), # 已安装应用程序连接方法(新增功能) lambda: Application(backend="uia").connect(title_re=".*Kiro.*", timeout=5), lambda: Application(backend="win32").connect(title_re=".*Kiro.*", timeout=5), lambda: Application(backend="uia").connect(title_re=".*Getting started.*", timeout=5), lambda: Application(backend="win32").connect(title_re=".*Getting started.*", timeout=5), lambda: Application(backend="uia").connect(path=app_path, timeout=5), lambda: Application(backend="win32").connect(path=app_path, timeout=5), ] app = None for i, attempt in enumerate(connection_attempts, 1): try: print(f" 尝试方法 {i}...") app = attempt() print(f"✅ 连接成功! (方法{i}) PID: {app.process}") break except Exception as e: print(f" 方法 {i} 失败: {str(e)[:50]}...") continue if not app: print("❌ 所有连接方法都失败了") return else: # 原有的连接逻辑 try: app = Application(backend="uia").connect(path=app_path, timeout=10) print(f"✅ 连接成功! PID: {app.process}") except: try: app = Application(backend="win32").connect(path=app_path, timeout=10) print(f"✅ 连接成功! (Win32模式) PID: {app.process}") except Exception as e: print(f"❌ 连接失败: {e}") return # 等待5秒 print("⏳ 等待5秒...") for i in range(5, 0, -1): print(f" {i}秒", end='\r') time.sleep(1) print(" 完成!") # 获取所有窗口 print("\n" + "="*60) print("🔍 分析窗口控件...") print("="*60) try: # 尝试多种方式获取窗口 print("🔍 尝试获取窗口...") windows = app.windows() print(f"📊 发现 {len(windows)} 个窗口") # 如果没有窗口,尝试其他方法 if len(windows) == 0: print("⚠️ 未发现窗口,尝试其他方法...") # 方法1:尝试获取顶级窗口 try: top_window = app.top_window() print(f"✅ 找到顶级窗口: {top_window.window_text()}") windows = [top_window] except Exception as e: print(f"❌ 获取顶级窗口失败: {e}") # 方法2:尝试通过进程ID查找所有窗口 if len(windows) == 0: try: from pywinauto import Desktop desktop = Desktop(backend="uia") all_windows = desktop.windows() kiro_windows = [] for win in all_windows: try: if win.process_id() == app.process: kiro_windows.append(win) except: continue if kiro_windows: print(f"✅ 通过进程ID找到 {len(kiro_windows)} 个窗口") windows = kiro_windows except Exception as e: print(f"❌ 通过进程ID查找失败: {e}") print(f"📊 最终发现 {len(windows)} 个窗口\n") for i, window in enumerate(windows, 1): try: title = window.window_text() class_name = window.class_name() visible = window.is_visible() print(f"🪟 窗口 {i}: {title or '[无标题]'}") print(f" 类名: {class_name}") print(f" 可见: {'是' if visible else '否'}") # 分析所有窗口,不管是否可见 print(" 📋 控件列表:") # 特殊处理InnoSetup窗口 if "InnoSetup" in title or "InnoSetup" in class_name: print(" 🔍 检测到InnoSetup安装程序,尝试激活窗口...") try: window.set_focus() window.restore() time.sleep(1) # 等待窗口激活 print(" ✅ 窗口已激活") except Exception as e: print(f" ⚠️ 激活窗口失败: {e}") # 获取所有控件 try: controls = window.descendants() print(f" 总控件数: {len(controls)}") # 显示前20个有用的控件 useful_controls = [] for ctrl in controls: try: text = ctrl.window_text().strip() ctrl_class_name = ctrl.class_name() # 获取UIA属性 control_type = "" automation_id = "" if hasattr(ctrl, 'element_info'): try: control_type = ctrl.element_info.control_type automation_id = ctrl.element_info.automation_id or "" except: pass # 过滤有用的控件 - 放宽条件,显示更多控件 if (text or automation_id or control_type or ctrl_class_name in ['Button', 'Edit', 'ComboBox', 'RadioButton', 'CheckBox', 'Static', 'TButton', 'TEdit'] or control_type in ['Button', 'Edit', 'ComboBox', 'RadioButton', 'CheckBox', 'Text', 'Window', 'Pane']): useful_controls.append({ 'text': text or '[无文本]', 'type': control_type or ctrl_class_name, 'auto_id': automation_id, 'class': ctrl_class_name, 'visible': ctrl.is_visible(), 'enabled': ctrl.is_enabled() }) if len(useful_controls) >= 20: break except: continue # 打印有用的控件 for j, ctrl_info in enumerate(useful_controls, 1): status = [] if not ctrl_info['visible']: status.append("隐藏") if not ctrl_info['enabled']: status.append("禁用") status_str = f" ({', '.join(status)})" if status else "" print(f" {j:2d}. {ctrl_info['text']}{status_str}") print(f" 类型: {ctrl_info['type']}") if ctrl_info['auto_id']: print(f" ID: {ctrl_info['auto_id']}") print(f" 类名: {ctrl_info['class']}") print() if len(controls) > len(useful_controls): print(f" ... 还有 {len(controls) - len(useful_controls)} 个其他控件") except Exception as e: print(f" ❌ 获取控件失败: {e}") print("-" * 50) except Exception as e: print(f"❌ 分析窗口 {i} 失败: {e}") except Exception as e: print(f"❌ 获取窗口失败: {e}") def main(): """主函数""" print("🚀 快速窗口控件分析器") print("="*40) # 获取应用程序路径 if len(sys.argv) > 1: app_path = sys.argv[1] else: app_path = input("请输入应用程序路径 (例如: kiro.exe): ").strip() if not app_path: print("❌ 未提供应用程序路径") return quick_analyze(app_path) print("\n✅ 分析完成!") if __name__ == "__main__": try: main() except KeyboardInterrupt: print("\n⚠️ 用户中断") except Exception as e: print(f"\n❌ 错误: {e}")