如何使用pywin32将已启动的Windows应用窗口与对应Python对象关联
解决方案
你之前的写法使用win32com.client.Dispatch("Excel.Application")默认只会绑定到系统中第一个启动的Excel实例,多次调用也只会返回同一个对象,所以才会两次都输出Book1。
实现步骤
- 先安装依赖:
pip install pywin32 - 核心逻辑:通过枚举Windows顶层窗口筛选Excel主窗口(类名固定为
XLMAIN),再通过窗口句柄(HWND)获取对应实例的COM对象。
完整可运行代码如下:
# -*- coding: utf-8 -*- import win32gui import win32com.client # Excel主窗口固定类名 EXCEL_WINDOW_CLASS = "XLMAIN" # 调用接口需要的固定常量 OBJID_NATIVEOM = 0xFFFFFFF0 def get_all_excel_instances(): excel_instances = [] # 窗口枚举回调函数 def enum_window_proc(hwnd, lParam): if win32gui.GetClassName(hwnd) == EXCEL_WINDOW_CLASS: try: # 从窗口句柄获取对应Excel COM对象 excel_window = win32gui.AccessibleObjectFromWindow(hwnd, OBJID_NATIVEOM) excel_app = win32com.client.Dispatch(excel_window).Application excel_instances.append(excel_app) except: pass return True win32gui.EnumWindows(enum_window_proc, None) return excel_instances if __name__ == "__main__": # 获取所有运行中的Excel实例 all_excel = get_all_excel_instances() # 遍历输出每个实例的工作簿信息 for index, exl in enumerate(all_excel, 1): print(f"第{index}个Excel实例的工作簿:") for wb in exl.Workbooks: print(f" {wb.FullName}")
使用说明
如果你已经提前获取了每个Excel实例对应的HWND和工作簿名称,只需要在枚举实例时匹配对应信息,即可拿到目标COM对象:
# 示例:获取打开了Book2的Excel实例 target_excel = None for exl in get_all_excel_instances(): for wb in exl.Workbooks: if wb.Name == "Book2": target_excel = exl break if target_excel: break # 后续直接操作target_excel即可 print(target_excel.ActiveWorkbook.FullName)
注意:如果Excel实例是以管理员权限启动的,Python脚本也需要以管理员权限运行,否则无法正常获取对应COM对象。
内容的提问来源于stack exchange,提问作者Gimbav
相关产品推荐
相关产品推荐

