我知道使用os.startfile('....')或os.system('....')可以运行一个文件,例如* .pdf,* .mp4等等,但它无法获得该文件的hwnd。 (我必须知道控制窗口的hwnd,例如,移动,调整大小或关闭它)
当然,我可以通过win32gui.FindWindow(无,“文件名”)获取hwnd,但是,如果有两个具有相同名称的窗口,则无法单独获取hwnd。
是否有一个函数可以运行文件并在win32中获取它的hwnd?
像这样:
hwnd=win32.function("file dir/file name") // run a file like os.startfile(...)
//hwnd=-1 if failed
//hwnd=1234567 if successful
然后我可以运行多个文件并毫无问题地获取它们。
提前致谢。
答案 0 :(得分:3)
首先,“hwnd”是一个含糊不清的概念。一个进程可以没有窗口或3000个窗口。
但是我们假设您正在运行一个总是只有1个窗口的程序,并且您需要知道哪些窗口属于您实际启动的进程,而不是比如已经运行的同一进程的另一个实例。 (否则你只能按标题和课程进行搜索。)
所以,你需要一些方法来引用这个过程。如果您使用os.system
或os.startfile
,则无法执行此操作,因此您会遇到困难。这只是使用subprocess
模块的众多原因之一:
p = subprocess.Popen(args)
pid = p.pid
现在,您只需enumerate all top-level windows,然后get the PID for each,并检查哪一个匹配。
假设您已安装pywin32
,并且您使用的是Python 3.x,它看起来像这样:
def find_window_for_pid(pid):
result = None
def callback(hwnd, _):
nonlocal result
ctid, cpid = win32process.GetWindowThreadProcessId(hwnd)
if cpid == pid:
result = hwnd
return False
return True
win32gui.EnumWindows(callback, None)
return result
在Python 2.x中,没有nonlocal
,所以你需要一些其他的方法来从你的回调中获取值到外部函数,比如围绕一个可变虚拟变量的闭包(比如result = [None]
,然后设置result[0]
而不是result
)。
但请注意,这很容易失败,因为当您第一次启动该过程时,它可能在几毫秒之后才会出现窗口。如果没有父母和孩子之间的某种同步手段,那么实际上没有办法解决这个问题。 (你可以通过,比如睡觉一秒钟来破解它,但这与任何尝试睡眠而不是同步的问题相同 - 大多数时候,它会太长,会减少代码的响应性/性能无缘无故,偶尔,当计算机繁忙时,它会太短而失败。)
真正解决此问题的唯一方法是使用pywin32
到create the process而不是使用标准Python代码。然后你有一个句柄到这个过程。这意味着您可以wait for the child to start its window loop,然后枚举该进程的窗口。