Получить активное окно с помощью Python
Я хотел бы получить активное окно на экране с помощью python.
Например, интерфейс управления маршрутизатором, в котором вы вводите имя пользователя и пароль как admin
Этот интерфейс администратора - это то, что я хочу захватить с помощью python для автоматизации ввода имени пользователя и пароля.
Какие импорт потребуются для этого?
Ответы
Ответ 1
В Windows вы можете использовать Python для расширений Windows (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/)
Ответ 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()