Files
kiro-automation-toolkit/sandbox_files/quick_analyzer.py
T
hotyi 85efecf0be 初始提交:Kiro IDE 自动化安装完整项目
🚀 项目特性:
- Windows Sandbox 环境支持
- 完整的自动化安装流程
- 智能等待和界面检测机制
- 多种登录方式支持
- 丰富的调试和分析工具

📁 项目结构:
- sandbox/ - 项目根目录
- sandbox_files/ - 沙盒环境脚本
- start_sandbox.ps1 - 主启动脚本
- sandbox_config.wsb - Sandbox 配置

🛠️ 核心功能:
- 自动化 Kiro IDE 安装
- 登录界面自动化
- 窗口和控件分析
- 详细的进度反馈

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-27 15:53:32 +08:00

239 lines
9.6 KiB
Python

#!/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}")