Получить активное окно с помощью Python

Я хотел бы получить активное окно на экране с помощью python.

Например, интерфейс управления маршрутизатором, в котором вы вводите имя пользователя и пароль как admin

Этот интерфейс администратора - это то, что я хочу захватить с помощью python для автоматизации ввода имени пользователя и пароля.

Какие импорт потребуются для этого?

Ответы

Ответ 2

Следующий script должен работать в Linux, Windows и Mac. В настоящее время он тестируется только на Linux (Ubuntu Mate Ubuntu 15.10).

Необходимые условия

Для Linux:

Установите wnck (sudo apt-get install python-wnck в Ubuntu, см. libwnck.)

Для Windows:

Убедитесь, что win32gui доступен

Для Mac:

Убедитесь, что AppKit доступен

script

#!/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()))

Ответ 3

Для пользователей Linux: для всех предоставленных ответов требовались дополнительные модули, такие как "wx", в которых были установлены многочисленные ошибки ("pip" не удалось собрать), но я смог довольно легко изменить это решение → исходный код. Были ошибки в оригинале (Python TypeError на регулярное выражение)

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 при установке с помощью "sudo apt-get install python-wnck", так как я использовал python3.x, единственным вариантом был pypie, который я не тестировал. Надеюсь, это поможет кому-то еще.

Ответ 4

Там действительно нет необходимости импортировать какие-либо внешние зависимости для таких задач, как это. Python поставляется с довольно аккуратным интерфейсом внешних функций - ctypes, который позволяет вызывать совместно используемые библиотеки C. Он даже включает специальные привязки для наиболее распространенных библиотек DLL Win32.

Например, чтобы получить PID окна foregorund:

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)

Ответ 5

Спасибо за ответ нуно Андре, который показал, как использовать ctypes для взаимодействия с API-интерфейсами Windows. Я написал пример реализации, используя его подсказки.

Библиотека ctypes включена в Python начиная с версии 2.5, что означает, что она есть практически у каждого пользователя. И этот интерфейс намного чище, чем старые и мертвые библиотеки, такие как win32gui (последнее обновление в 2017 году на момент написания статьи).

Документация находится здесь: https://docs.python.org/3/library/ctypes.html (Вы должны прочитать справку по его использованию, если хотите написать свой собственный код, в противном случае вы можете вызвать сбой сегментации, хе-хе.)

В основном, ctypes включает в себя привязки для наиболее распространенных библиотек DLL Windows. Вот как вы можете получить заголовок окна переднего плана в чистом Python, без каких-либо внешних библиотек! Просто встроенные ctypes!: -)

Самое классное в ctypes - это то, что вы можете использовать Google любой API Windows для всего, что вам нужно, и если вы хотите его использовать, вы можете сделать это через 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 -terminator).

Функция create_unicode_buffer выделяет место для такого количества символов UTF-16.

Большинство (или все? Всегда читают документы Microsoft MSDN!) API-интерфейсы Windows, связанные с текстом Unicode, принимают длину буфера как CHARACTERS, а НЕ как байты.

Также внимательно посмотрите на вызовы функций. Некоторые заканчиваются на W (например, GetWindowTextLengthW). Это означает "Широкая строка", которая является именем Windows для строк Юникода. Очень важно, чтобы вы выполняли эти вызовы W, чтобы получить правильные строки Unicode (с поддержкой международных символов).

PS: Windows давно использует Юникод. Я точно знаю, что Windows 10 полностью Unicode и хочет только вызовы функций W. Я не знаю точную дату окончания, когда более старые версии Windows использовали другие многобайтовые форматы строк, но я думаю, что это было до Windows Vista, и кого это волнует? Старые версии Windows (даже 7 и 8.1) устарели и не поддерживаются Microsoft.

Снова... наслаждайтесь! :-)

Ответ 6

Просто хотел добавить в случае, если это поможет, у меня есть функция для моей программы (это программное обеспечение для моего освещения ПК. У меня есть эта простая небольшая линейная функция:

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

Ответ 7

Попробуйте использовать wxPython:

import wx
wx.GetActiveWindow()