使用Python获取Active窗口

时间:2012-04-22 08:08:05

标签: python active-window

我想使用python在屏幕上显示活动窗口。

例如,路由器的管理界面,您输入用户名和密码为admin

我希望使用python捕获该管理界面以自动输入用户名和密码。

为了做到这一点,我需要哪些进口产品?

9 个答案:

答案 0 :(得分:18)

在Windows上,您可以使用python for windows extensions(http://sourceforge.net/projects/pywin32/):

from win32gui import GetWindowText, GetForegroundWindow
print GetWindowText(GetForegroundWindow())

以下代码适用于python 3:

from win32gui import GetWindowText, GetForegroundWindow
print(GetWindowText(GetForegroundWindow()))

(在http://scott.sherrillmix.com/blog/programmer/active-window-logger/上找到)

答案 1 :(得分:11)

以下脚本应适用于Linux,Windows和Mac。它目前仅在Linux(Ubuntu Mate Ubuntu 15.10)上进行测试。

先决条件

适用于Linux

在Ubuntu上安装wncksudo apt-get install python-wnck,请参阅libwnck。)

适用于Windows

确保win32gui可用

适用于Mac

确保AppKit可用

脚本

#!/usr/bin/env python

"""Find the currently active window."""

import logging
import sys

logging.basicConfig(format='%(asctime)s %(levelname)s %(message)s',
                    level=logging.DEBUG,
                    stream=sys.stdout)


def get_active_window():
    """
    Get the currently active window.

    Returns
    -------
    string :
        Name of the currently active window.
    """
    import sys
    active_window_name = None
    if sys.platform in ['linux', 'linux2']:
        # Alternatives: http://unix.stackexchange.com/q/38867/4784
        try:
            import wnck
        except ImportError:
            logging.info("wnck not installed")
            wnck = None
        if wnck is not None:
            screen = wnck.screen_get_default()
            screen.force_update()
            window = screen.get_active_window()
            if window is not None:
                pid = window.get_pid()
                with open("/proc/{pid}/cmdline".format(pid=pid)) as f:
                    active_window_name = f.read()
        else:
            try:
                from gi.repository import Gtk, Wnck
                gi = "Installed"
            except ImportError:
                logging.info("gi.repository not installed")
                gi = None
            if gi is not None:
                Gtk.init([])  # necessary if not using a Gtk.main() loop
                screen = Wnck.Screen.get_default()
                screen.force_update()  # recommended per Wnck documentation
                active_window = screen.get_active_window()
                pid = active_window.get_pid()
                with open("/proc/{pid}/cmdline".format(pid=pid)) as f:
                    active_window_name = f.read()
    elif sys.platform in ['Windows', 'win32', 'cygwin']:
        # http://stackoverflow.com/a/608814/562769
        import win32gui
        window = win32gui.GetForegroundWindow()
        active_window_name = win32gui.GetWindowText(window)
    elif sys.platform in ['Mac', 'darwin', 'os2', 'os2emx']:
        # http://stackoverflow.com/a/373310/562769
        from AppKit import NSWorkspace
        active_window_name = (NSWorkspace.sharedWorkspace()
                              .activeApplication()['NSApplicationName'])
    else:
        print("sys.platform={platform} is unknown. Please report."
              .format(platform=sys.platform))
        print(sys.version)
    return active_window_name

print("Active window: %s" % str(get_active_window()))

答案 2 :(得分:3)

对于Linux用户: 提供的所有答案都需要额外的模块,如" wx"这有很多错误安装(" pip"构建失败),但我能够很容易地修改这个解决方案 - > original source。原始版本中存在错误(Python TypeError on regex

import sys
import os
import subprocess
import re

def get_active_window_title():
    root = subprocess.Popen(['xprop', '-root', '_NET_ACTIVE_WINDOW'], stdout=subprocess.PIPE)
    stdout, stderr = root.communicate()

    m = re.search(b'^_NET_ACTIVE_WINDOW.* ([\w]+)$', stdout)
    if m != None:
        window_id = m.group(1)
        window = subprocess.Popen(['xprop', '-id', window_id, 'WM_NAME'], stdout=subprocess.PIPE)
        stdout, stderr = window.communicate()
    else:
        return None

    match = re.match(b"WM_NAME\(\w+\) = (?P<name>.+)$", stdout)
    if match != None:
        return match.group("name").strip(b'"')

    return None

if __name__ == "__main__":
    print(get_active_window_title())

优点是无需额外模块即可工作。如果您希望它跨多个平台工作,只需更改命令和正则表达式字符串即可根据平台获取所需数据(使用上面显示的标准if / else平台检测 sys .platform )。

旁注:导入wnck只能与python2.x一起使用&#34; sudo apt-get install python-wnck&#34;,因为我使用python3.x唯一的选择是pypie我有未经测试。希望这有助于其他人。

答案 3 :(得分:1)

感谢NunoAndré的回答,他展示了如何使用ctypes与Windows API进行交互。我已经利用他的提示编写了一个示例实现。

自v2.5起,Python已包含ctypes库,这意味着几乎每个用户都拥有它。而且它是比win32gui(在撰写本文时于2017年更新)之类的老旧库更干净的界面。

文档在这里:https://docs.python.org/3/library/ctypes.html(如果您想编写自己的代码,则必须阅读其使用帮助,否则会导致分段错误崩溃,呵呵。)

基本上,ctypes包含最常见Windows DLL的绑定。这是您无需外部库即可在纯Python中检索前台窗口标题的方法!只是内置的ctypes! :-)

关于ctypes的最酷的事情是,您可以使用Google 任何 Windows API来获取所需的任何内容,如果要使用它,您可以 通过ctypes进行操作!

Python 3代码:

from typing import Optional
from ctypes import wintypes, windll, create_unicode_buffer

def getForegroundWindowTitle() -> Optional[str]:
    hWnd = windll.user32.GetForegroundWindow()
    length = windll.user32.GetWindowTextLengthW(hWnd)
    buf = create_unicode_buffer(length + 1)
    windll.user32.GetWindowTextW(hWnd, buf, length + 1)

    # 1-liner alternative: return buf.value if buf.value else None
    if buf.value:
        return buf.value
    else:
        return None

性能非常好:0.01在计算机上发生故障(0.00001秒)。

在Python 2上也可以进行很小的改动。如果您使用的是Python 2,我认为您只需删除类型注释(from typing import Optional-> Optional[str])。 :-)

享受!

Win32技术说明:

length变量是UTF-16(Windows宽域“ Unicode”)字符中实际文本的长度。(不是数字我们必须添加+ 1,以在C样式字符串的末尾为空终止符增加空间。如果不这样做,则缓冲区中将没有足够的空间来容纳实际文本的最终实际字符,Windows将截断返回的字符串(这样做是为了确保它适合超重要的最终字符串Null -终止符)。

create_unicode_buffer函数为许多UTF-16字符分配空间。

大多数(或全部?总是要阅读Microsoft的MSDN文档!!)与Unicode文本相关的Windows API的缓冲区长度为CHARACTERS,不为字节。

还要仔细查看函数调用。某些以W结尾(例如GetWindowTextLengthW)。这代表“宽字符串”,这是Unicode字符串的Windows名称。进行这些W调用以获取正确的Unicode字符串(具有国际字符支持)非常重要。

PS:Windows长期以来一直使用Unicode。我知道Windows 10是完全 Unicode的事实,并且只需要W函数调用。我不知道旧版本的Windows使用 other 多字节字符串格式的确切截止日期,但是我认为它早于Windows Vista,谁在乎?旧的Windows版本(甚至是7和8.1)已失效,Microsoft不支持。

再次...享受! :-)

答案 4 :(得分:0)

只是想添加以防它有用,我有一个功能为我的程序(它是我的电脑和照明的软件我有这个简单的几行功能:

def isRunning(process_name):
   foregroundWindow = GetWindowText(GetForegroundWindow())
   return process_name in foregroundWindow

答案 5 :(得分:0)

对于这样的任务,实际上不需要导入任何外部依赖项。 Python带有一个非常简洁的外部函数接口-ctypes,它允许本地调用C共享库。它甚至包括最常见的Win32 DLL的特定绑定。

例如获取前窗窗口的PID:

import ctypes
from ctypes import wintypes

user32 = ctypes.windll.user32

h_wnd = user32.GetForegroundWindow()
pid = wintypes.DWORD()
user32.GetWindowThreadProcessId(h_wnd, ctypes.byref(pid))
print(pid.value)

答案 6 :(得分:0)

我在linux接口(Lubuntu 20)上也遇到了同样的问题。 我要做的是使用wmctrl并通过python的shell命令执行它。

首先,安装wmctrl sudo apt install wmctrl

然后,添加此代码:

import os
os.system('wmctrl -a "Mozilla Firefox"')

ref wmctrl: https://askubuntu.com/questions/21262/shell-command-to-bring-a-program-window-in-front-of-another

答案 7 :(得分:0)

在 X11 下的 Linux 中:

xdo_window_id = os.popen('xdotool getactivewindow').read()
print('xdo_window_id:', xdo_window_id)

将以十进制格式打印活动窗口 ID:

xdo_window_id: 67113707

注意 xdotool 必须先安装:

sudo apt install xdotool

注意 wmctrl 使用十六进制格式作为窗口 ID。

答案 8 :(得分:-6)

尝试使用wxPython:

import wx
wx.GetActiveWindow()