使用进程名称获取另一个程序窗口的标题

时间:2015-07-07 20:25:30

标签: python windows

这个问题可能很基本,但我很难破解它。我假设我必须使用ctypes.windll.user32中的内容。请记住,我几乎没有经验使用这些库甚至整个ctypes

我已使用此代码列出所有窗口标题,但我不知道如何更改此代码以获取带有进程名称的窗口标题:

import ctypes

EnumWindows = ctypes.windll.user32.EnumWindows
EnumWindowsProc = ctypes.WINFUNCTYPE(ctypes.c_bool, ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_int))
GetWindowText = ctypes.windll.user32.GetWindowTextW
GetWindowTextLength = ctypes.windll.user32.GetWindowTextLengthW
IsWindowVisible = ctypes.windll.user32.IsWindowVisible

titles = []
def foreach_window(hwnd, lParam):
    if IsWindowVisible(hwnd):
        length = GetWindowTextLength(hwnd)
        buff = ctypes.create_unicode_buffer(length + 1)
        GetWindowText(hwnd, buff, length + 1)
        titles.append(buff.value)
    return True
EnumWindows(EnumWindowsProc(foreach_window), 0)

print(titles)

此代码来自https://sjohannes.wordpress.com/2012/03/23/win32-python-getting-all-window-titles/

如果我的问题不清楚,我想实现这样的事情(只是一个例子 - 我并没有具体询问Spotify):

getTitleOfWindowbyProcessName("spotify.exe") // returns "Avicii - Waiting For Love" (or whatever the title is)

如果有多个窗口运行相同的进程名称(例如多个镀铬窗口),则可能出现复杂情况

谢谢。

编辑:为了澄清,我想要一些采用进程名称的代码,并将该进程拥有的窗口标题列表(可能为空)作为字符串返回。

1 个答案:

答案 0 :(得分:3)

这是我在评论中的意思:

import win32gui


def enumWindowsProc(hwnd, lParam):
    print win32gui.GetWindowText(hwnd)

win32gui.EnumWindows(enumWindowsProc, 0)

下面,我粘贴了整个事情......它现在不能用于我现在的 PC ,因为我搞砸了安全设置(它是' s一个 XP !!!)我得到了一堆访问被拒绝(错误代码: 5 )错误,但在这里。

code.py

#!/usr/bin/env python3

import sys
import os
import traceback
import ctypes
from ctypes import wintypes
import win32con
import win32api
import win32gui
import win32process


def enumWindowsProc(hwnd, lParam):
    if (lParam is None) or ((lParam is not None) and (win32process.GetWindowThreadProcessId(hwnd)[1] == lParam)):
        text = win32gui.GetWindowText(hwnd)
        if text:
            wStyle = win32api.GetWindowLong(hwnd, win32con.GWL_STYLE)
            if wStyle & win32con.WS_VISIBLE:
                print("%08X - %s" % (hwnd, text))


def enumProcWnds(pid=None):
    win32gui.EnumWindows(enumWindowsProc, pid)


def enumProcs(procName=None):
    pids = win32process.EnumProcesses()
    if procName is not None:
        bufLen = 0x100

        _OpenProcess = ctypes.cdll.kernel32.OpenProcess
        _OpenProcess.argtypes = [wintypes.DWORD, wintypes.BOOL, wintypes.DWORD]
        _OpenProcess.restype = wintypes.HANDLE

        _GetProcessImageFileName = ctypes.cdll.psapi.GetProcessImageFileNameA
        _GetProcessImageFileName.argtypes = [wintypes.HANDLE, wintypes.LPSTR, wintypes.DWORD]
        _GetProcessImageFileName.restype = wintypes.DWORD

        _CloseHandle = ctypes.cdll.kernel32.CloseHandle
        _CloseHandle.argtypes = [wintypes.HANDLE] 
        _CloseHandle.restype = wintypes.BOOL

        filteredPids = ()
        for pid in pids:
            try:
                hProc = _OpenProcess(win32con.PROCESS_ALL_ACCESS, 0, pid)
            except:
                print("Process [%d] couldn't be opened: %s" % (pid, traceback.format_exc()))
                continue
            try:
                buf = ctypes.create_string_buffer(bufLen)
                _GetProcessImageFileName(hProc, buf, bufLen)
                if buf.value:
                    name = buf.value.decode().split(os.path.sep)[-1]
                    #print name
                else:
                    _CloseHandle(hProc)
                    continue
            except:
                print("Error getting process name: %s" % traceback.format_exc())
                _CloseHandle(hProc)
                continue
            if name.lower() == procName.lower():
                filteredPids += (pid,)
        return filteredPids
    else:
        return pids


def main(args):
    if args:
        procName = args[0]
    else:
        procName = None
    pids = enumProcs(procName)
    #print(pids)
    for pid in pids:
        enumProcWnds(pid)


if __name__ == "__main__":
    print("Python {:s} on {:s}\n".format(sys.version, sys.platform))
    main(sys.argv[1:])

毋庸置疑:

  • 为了使此代码有效,您需要以特权用户身份运行它( Administrator );至少 SeDebugPrivilege [MS.Docs]: Privilege Constants)是必需的。
  • 当进程以 32/64位模式运行时,可能会出现意外情况(执行此代码的 python 进程,以及由此枚举的目标进程)代码)