Je voudrais afficher la fenêtre active à l'écran en utilisant python.
Par exemple, l'interface de gestion du routeur où vous entrez le nom d'utilisateur et le mot de passe en tant qu'administrateur
Cette interface d'administration est ce que je veux capturer en utilisant python pour automatiser la saisie du nom d'utilisateur et du mot de passe.
De quelles importations aurais-je besoin pour ce faire?
Sur Windows, vous pouvez utiliser le python pour les extensions Windows ( http://sourceforge.net/projects/pywin32/ ):
from win32gui import GetWindowText, GetForegroundWindow
print GetWindowText(GetForegroundWindow())
Le code ci-dessous est pour python 3:
from win32gui import GetWindowText, GetForegroundWindow
print(GetWindowText(GetForegroundWindow()))
(Trouvé ceci sur http://scott.sherrillmix.com/blog/programmer/active-window-logger/ )
Le script suivant devrait fonctionner sur Linux, Windows et Mac. Il n'est actuellement testé que sur Linux (Ubuntu Mate Ubuntu 15.10).
Pour Linux :
Installez wnck
(Sudo apt-get install python-wnck
sur Ubuntu, voir libwnck .)
Pour Windows :
Assure-toi win32gui
est disponible
Pour Mac :
Assurez-vous que AppKit
est disponible
#!/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()))
Il n'est vraiment pas nécessaire d'importer de dépendance externe pour des tâches comme celle-ci. Python est livré avec une interface de fonction étrangère assez soignée - ctypes
, qui permet d'appeler nativement les bibliothèques partagées C. Il inclut même des liaisons spécifiques pour la plupart DLL Win32 courantes.
Par exemple. pour obtenir le PID de la fenêtre précédente:
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)
Pour les utilisateurs de Linux: Toutes les réponses fournies nécessitaient des modules supplémentaires comme "wx" qui avaient de nombreuses erreurs d'installation ("pip" a échoué à la construction), mais j'ai pu modifier cette solution assez facilement -> source d'origine . Il y avait des bugs dans l'original ( Python TypeError sur 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())
L'avantage est qu'il fonctionne sans modules supplémentaires. Si vous voulez qu'il fonctionne sur plusieurs plates-formes, il suffit de changer la chaîne de commande et l'expression régulière pour obtenir les données que vous souhaitez en fonction de la plate-forme (avec la détection de plate-forme standard if/else indiquée ci-dessus sys.platform ).
Sur une note latérale: l'importation wnck ne fonctionne qu'avec python2.x lorsqu'il est installé avec "Sudo apt-get install python-wnck", puisque j'utilisais python3.x la seule option était pypie que je n'ai pas testée. J'espère que ceci aide quelqu'un d'autre.
Merci à la réponse de Nuno André, qui a montré comment utiliser les ctypes pour interagir avec les API Windows. J'ai écrit un exemple d'implémentation en utilisant ses conseils.
La bibliothèque ctypes
est incluse avec Python depuis la v2.5, ce qui signifie que presque tous les utilisateurs l'ont. Et c'est une interface beaucoup plus propre que les bibliothèques anciennes et mortes comme win32gui
(dernière mise à jour en 2017 au moment de la rédaction de cet article).
La documentation est ici: https://docs.python.org/3/library/ctypes.html (Vous devez lire son aide à l'utilisation si vous voulez écrire votre propre code, sinon vous pouvez provoquer des plantages d'erreur de segmentation , hehe.)
Fondamentalement, ctypes inclut des liaisons pour les DLL Windows les plus courantes. Voici comment récupérer le titre de la fenêtre de premier plan en Python pur, sans avoir besoin de bibliothèques externes! Juste les ctypes intégrés! :-)
La chose la plus cool à propos des ctypes est que vous pouvez Google any API Windows pour tout ce dont vous avez besoin, et si vous voulez l'utiliser, vous pouvez le faire via ctypes !
Code 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
Les performances sont extrêmement bonnes: 0.01
MILLISECONDS sur mon ordinateur (0.00001
secondes).
Fonctionnera également sur Python 2 avec des modifications très mineures. Si vous êtes sur Python 2, je pense que vous n'avez qu'à supprimer les annotations de type (from typing import Optional
et -> Optional[str]
). :-)
Prendre plaisir!
Explications techniques Win32:
La variable length
est la longueur des caractères réels en UTF-16 (Windows Wide "Unicode") CARACTÈRES. (Ce n'est PAS le nombre d'octets.) Nous devons ajouter + 1
pour ajouter de l'espace pour le terminateur nul à la fin des chaînes de style C. Si nous ne le faisons pas, nous n'aurions pas assez d'espace dans le tampon pour ajuster le caractère réel final du texte réel, et Windows tronquerait la chaîne retournée (il le fait pour s'assurer qu'il correspond à la chaîne finale super importante Null -terminateur).
Le create_unicode_buffer
la fonction alloue de la place pour autant de PERSONNAGES UTF-16.
La plupart (ou tous? Lisez toujours les documents MSDN de Microsoft!) Les API Windows liées au texte Unicode prennent la longueur du tampon en CARACTÈRES, PAS en octets.
Regardez également attentivement les appels de fonction. Certains se terminent par W
(tels que GetWindowTextLengthW
). Cela signifie "chaîne large", qui est le nom Windows pour les chaînes Unicode. Il est très important que vous fassiez ces appels W
pour obtenir les chaînes Unicode appropriées (avec prise en charge des caractères internationaux).
PS: Windows utilise Unicode depuis longtemps. Je sais pertinemment que Windows 10 est entièrement Unicode et ne veut que les appels de fonction W
. Je ne connais pas la date limite exacte lorsque les anciennes versions de Windows utilisaient des formats de chaîne multi-octets autre, mais je pense que c'était avant Windows Vista, et qui s'en soucie? Les anciennes versions de Windows (même 7 et 8.1) sont mortes et non prises en charge par Microsoft.
Encore une fois ... profitez-en! :-)
Je voulais juste ajouter au cas où cela aiderait, j'ai une fonction pour mon programme (c'est un logiciel pour l'éclairage de mon PC, j'ai cette simple fonction de quelques lignes:
def isRunning(process_name):
foregroundWindow = GetWindowText(GetForegroundWindow())
return process_name in foregroundWindow