从PID设置Active / Foreground窗口

时间:2017-09-16 13:20:35

标签: python subprocess pywin32

我正在尝试将程序(已知PID)设置为top / active / foreground(不确定哪个是最合适的)。

PID设置为Windows进程PID

    handle = win32api.OpenProcess( win32con.PROCESS_ALL_ACCESS,
                        False, pid)
    win32gui.SetForegroundWindow(handle)
    win32gui.SetActiveWindow(handle)

我得到:

    pywintypes.error: (1400, 'SetForegroundWindow', 'Invalid window Handle.')

    pywintypes.error: (1400, 'SetActiveWindow', 'Invalid window handle.')

我意识到这是处理程序中的问题,但我不确定我应该如何正确地获得工作句柄。

2 个答案:

答案 0 :(得分:3)

这项工作可以通过pywinauto完成:

from pywinauto import Application
app = Application().connect(process=<pid>)
app.top_window().set_focus()

但它可能不适用于最小化的应用程序。

答案 1 :(得分:2)

OpenProcess函数:

如果函数成功,则返回值是指定进程的打开句柄。它可以在任何需要处理句柄的函数中使用。

SetForegroundWindow函数:

它的参数是窗口的句柄,应该被激活并带到前台。

所以你需要这样的翻译:

HWND h = ::GetTopWindow(0 );
while ( h )
{
  DWORD pid;
  DWORD dwTheardId = ::GetWindowThreadProcessId( h,&pid);
         if ( pid == /*your process id*/ )
         {
              // here h is the handle to the window
              break;
         }
         h = ::GetNextWindow( h , GW_HWNDNEXT);
}

python版本:

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

一些注意事项:

  

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

真正解决这个问题的唯一方法是使用pywin32创建进程而不是使用标准Python代码。然后你就可以了解这个过程。这意味着您可以等待孩子开始其窗口循环,然后枚举该过程的窗口。