如何在python中使用win32运行文件并获取hwnd?

时间:2013-12-12 02:13:32

标签: python winapi

我知道使用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

然后我可以运行多个文件并毫无问题地获取它们。

提前致谢。

1 个答案:

答案 0 :(得分:3)

首先,“hwnd”是一个含糊不清的概念。一个进程可以没有窗口或3000个窗口。

但是我们假设您正在运行一个总是只有1个窗口的程序,并且您需要知道哪些窗口属于您实际启动的进程,而不是比如已经运行的同一进程的另一个实例。 (否则你只能按标题和课程进行搜索。)

所以,你需要一些方法来引用这个过程。如果您使用os.systemos.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)。


但请注意,这很容易失败,因为当您第一次启动该过程时,它可能在几毫秒之后才会出现窗口。如果没有父母和孩子之间的某种同步手段,那么实际上没有办法解决这个问题。 (你可以通过,比如睡觉一秒钟来破解它,但这与任何尝试睡眠而不是同步的问题相同 - 大多数时候,它会太长,会减少代码的响应性/性能无缘无故,偶尔,当计算机繁忙时,它会太短而失败。)

真正解决此问题的唯一方法是使用pywin32create the process而不是使用标准Python代码。然后你有一个句柄到这个过程。这意味着您可以wait for the child to start its window loop,然后枚举该进程的窗口。