简体   繁体   English

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

[英]How to run a file and get the hwnd using win32 in python?

I know using os.startfile('....') or os.system('....') can run a file, for example, *.pdf, *.mp4 and so on, but it can't get the hwnd of that file. 我知道使用os.startfile('....')或os.system('....')可以运行文件,例如* .pdf,*。mp4等,但不能获取该文件的hwnd。 (I have to know the hwnd to control the window, for instance, move, resize, or close it) (我必须知道hwnd来控制窗口,例如,移动,调整大小或关闭它)

Of course, I can get the hwnd by win32gui.FindWindow(None,"file name"), however, it can't get hwnd separately if there are two windows which have the same name. 当然,我可以通过win32gui.FindWindow(None,“ file name”)获得hwnd,但是,如果有两个具有相同名称的窗口,则无法分别获取hwnd。

Is there a function can run a file and get its hwnd in win32? 是否有功能可以运行文件并在win32中获取其hwnd?

Like this: 像这样:

hwnd=win32.function("file dir/file name") // run a file like os.startfile(...)

//hwnd=-1 if failed

//hwnd=1234567 if successful

and then I can run multiple files and get their hwnd without any problem. 然后我可以运行多个文件并毫无问题地获取它们的hwnd。

Thanks in advance. 提前致谢。

First, "the hwnd" is an ambiguous concept. 首先,“ hwnd”是一个模棱两可的概念。 A process can have no windows, or 3000 windows. 一个进程可以没有窗口,也可以没有3000个窗口。

But let's assume you happen to be running a program that always has exactly 1 window, and you need to know which windows belongs to the process you actually launched rather than, say, another instance of the same process already running. 但是,让我们假设您正在运行的程序始终只有一个窗口,并且您需要知道哪些窗口属于您实际启动的进程,而不是已经运行的同一进程的另一个实例。 (Otherwise you could just search by title and class.) (否则,您可以按标题和类别进行搜索。)

So, you need some way to refer the process. 因此,您需要某种方式来引用该过程。 If you're using os.system or os.startfile , you have no way to do that, so you're stuck. 如果您使用的是os.systemos.startfile ,则无法执行此操作,因此会陷入困境。 This is just one of the many, many reasons to use the subprocess module instead: 这只是代替使用subprocess模块的众多原因之一:

p = subprocess.Popen(args)
pid = p.pid

Now, you just enumerate all top-level windows , then get the PID for each , and check which one matches. 现在,您只枚举所有顶级窗口 ,然后获取每个 窗口 的PID并检查匹配的窗口

Assuming you have pywin32 installed, and you're using Python 3.x, it looks like this: 假设您已经安装了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

In Python 2.x, there's no nonlocal , so you need some other way to get the value from your callback to the outer function, like a closure around a mutable dummy variable (like result = [None] , then set result[0] instead of result ). 在Python 2.x中,没有nonlocal变量,因此您需要其他方法来将值从回调函数获取到外部函数,例如围绕可变变量的闭包(例如result = [None] ,然后设置result[0]而不是result )。


But note that this can easily fail, because when you first launch the process, it probably doesn't have a window until a few milliseconds later. 但是请注意,这很容易失败,因为当您首次启动该过程时,它可能直到几毫秒后才没有窗口。 Without some means of synchronizing between the parent and child, there's really no way around this. 如果没有父母与孩子之间进行同步的任何手段,那么实际上是无法解决的。 (You can hack it by, say, sleeping for a second, but that has the same problem as any attempt to sleep instead of synchronizing—most of the time, it'll be way too long, reducing the responsiveness/performance of your code for no reason, and occasionally, when the computer is busy, it'll be too short and fail.) (你可以通过破解,比方说,睡了一秒钟,但具有相同的问题,因为任何试图入睡,而不是同步,大部分的时间,这将是时间太长,减少你的代码的响应/性能无缘无故,偶尔,当计算机繁忙时,它会变得太短而失败。)

The only way to really solve this is to use pywin32 to create the process instead of using standard Python code. 真正解决此问题的唯一方法是使用pywin32 创建过程,而不是使用标准的Python代码。 Then you have a handle to the process. 然后,您可以处理该过程。 This means you can wait for the child to start its window loop , then enumerate just that process's windows. 这意味着您可以等待孩子开始其窗口循环 ,然后仅枚举该进程的窗口。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM