win32gui shows some windows, that are not open - python

I'm using the win32gui package for the first time. I found the following examples to printout all opened windows.
But I am wondering about that the log_app_list() function contains windows, that are not opened. For example 'Microsoft Store' and 'Einstellungen' (means settings in german). Can someone explain me this unexpected behavior?
import win32gui
def window_enum_handler(hwnd, resultList):
if win32gui.IsWindowVisible(hwnd) and win32gui.GetWindowText(hwnd) != '':
resultList.append((hwnd, win32gui.GetWindowText(hwnd)))
def get_app_list(handles=[]):
mlst=[]
win32gui.EnumWindows(window_enum_handler, handles)
for handle in handles:
mlst.append(handle)
return mlst
def log_app_list():
appwindows = get_app_list()
for i in appwindows:
print(i)
log_app_list()

It depends on the state of the process in the background, these windows are not "unopened", but the process is in the suspended state, you can check in the task manager, and The process "WinStore.App.exe" and "SystemSettings.exe" is in Suspended status:
You could use DwmGetWindowAttribute with DWMWA_CLOAKED to get its cloaked property, to exclude them:
import win32gui
import ctypes
from ctypes import c_int
import ctypes.wintypes
from ctypes.wintypes import HWND, DWORD
dwmapi = ctypes.WinDLL("dwmapi")
DWMWA_CLOAKED = 14
isCloacked = c_int(0)
def window_enum_handler(hwnd, resultList):
if win32gui.IsWindowVisible(hwnd) and win32gui.GetWindowText(hwnd) != '':
dwmapi.DwmGetWindowAttribute(HWND(hwnd), DWORD(DWMWA_CLOAKED), ctypes.byref(isCloacked), ctypes.sizeof(isCloacked))
if(isCloacked.value == 0):
resultList.append((hwnd, win32gui.GetWindowText(hwnd)))
def get_app_list(handles=[]):
mlst=[]
win32gui.EnumWindows(window_enum_handler, handles)
for handle in handles:
mlst.append(handle)
return mlst
def log_app_list():
appwindows = get_app_list()
for i in appwindows:
print(i)
log_app_list()

Related

Python console Fullscreen? Maybe using os.system?

I'm trying to figure out how to get my program to open in a fullscreen console window.
Is there any command that you can type within the command prompt to toggle fullscreen?
If so I'd imagine the code going something like:
from os import system
system("toggle.fullscreen")
{CODE HERE}
I understand mode con can be used, but that doesn't actually toggle it being maximized, which would be much more useful for me, thanks!
Here's a function to maximize the current console window. It uses ctypes to call WinAPI functions. First it calls GetLargestConsoleWindowSize in order to figure how big it can make the window, with the option to specify a number of lines that exceeds this in order to get a scrollback buffer. To do the work of resizing the screen buffer it simply calls mode.com via subprocess.check_call. Finally, it gets the console window handle via GetConsoleWindow and calls ShowWindow to maximize it.
import os
import ctypes
import msvcrt
import subprocess
from ctypes import wintypes
kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
user32 = ctypes.WinDLL('user32', use_last_error=True)
SW_MAXIMIZE = 3
kernel32.GetConsoleWindow.restype = wintypes.HWND
kernel32.GetLargestConsoleWindowSize.restype = wintypes._COORD
kernel32.GetLargestConsoleWindowSize.argtypes = (wintypes.HANDLE,)
user32.ShowWindow.argtypes = (wintypes.HWND, ctypes.c_int)
def maximize_console(lines=None):
fd = os.open('CONOUT$', os.O_RDWR)
try:
hCon = msvcrt.get_osfhandle(fd)
max_size = kernel32.GetLargestConsoleWindowSize(hCon)
if max_size.X == 0 and max_size.Y == 0:
raise ctypes.WinError(ctypes.get_last_error())
finally:
os.close(fd)
cols = max_size.X
hWnd = kernel32.GetConsoleWindow()
if cols and hWnd:
if lines is None:
lines = max_size.Y
else:
lines = max(min(lines, 9999), max_size.Y)
subprocess.check_call('mode.com con cols={} lines={}'.format(
cols, lines))
user32.ShowWindow(hWnd, SW_MAXIMIZE)
You can use keyboard.press. Install with pip3 install keyboard if it is not installed.
Code:
import keyboard
keyboard.press('f11')
I found this awhile back on a different post and it works perfectly for console window maximization:
import win32gui, win32con
hwnd = win32gui.GetForegroundWindow()
win32gui.ShowWindow(hwnd, win32con.SW_MAXIMIZE)

Python win32gui SetAsForegroundWindow function not working properly

I am trying to write a program that finds a window by searching for its title. Once it has found the window, it will attempt to bring it to front. I am using win32gui API to achieve this. I am able to get it to work for the most part, but for some reason it does not work if the taskmanager is in front. I have the follow sample code.
import win32gui, win32con
import re, traceback
from time import sleep
class cWindow:
def __init__(self):
self._hwnd = None
def BringToTop(self):
win32gui.BringWindowToTop(self._hwnd)
def SetAsForegroundWindow(self):
win32gui.SetForegroundWindow(self._hwnd)
def Maximize(self):
win32gui.ShowWindow(self._hwnd, win32con.SW_MAXIMIZE)
def setActWin(self):
win32gui.SetActiveWindow(self._hwnd)
def _window_enum_callback(self, hwnd, wildcard):
'''Pass to win32gui.EnumWindows() to check all the opened windows'''
if re.match(wildcard, str(win32gui.GetWindowText(hwnd))) != None:
self._hwnd = hwnd
def find_window_wildcard(self, wildcard):
self._hwnd = None
win32gui.EnumWindows(self._window_enum_callback, wildcard)
def main():
sleep(5)
try:
wildcard = ".*Building Operation WorkStation.*"
cW = cWindow()
cW.find_window_wildcard(wildcard)
cW.Maximize()
cW.BringToTop()
cW.SetAsForegroundWindow()
except:
f = open("log.txt", "w")
f.write(traceback.format_exc())
print traceback.format_exc()
main()
I pieced this together from multiple online sources. It seems to work for the most part but for some windows like the task manager, it'll work sometimes but fails the rest. When it doesnt work properly, all I notice is the application icon blinks yellow. Is there a proper way of doing this to make sure the window that I am interested in is set to foreground 100% of the times? I am not sure if this is relevant but I am using Windows 7 Professional (32-bit) with Service Pack 1.
I found a solution: if taskmanager, then kill it. I added a method to cWindow:
def kill_task_manager(self):
# Here I use your method to find a window because of an accent in my french OS,
# but you should use win32gui.FindWindow(None, 'Task Manager complete name').
wildcard = 'Gestionnaire des t.+ches de Windows'
self.find_window_wildcard(wildcard)
if self._hwnd:
win32gui.PostMessage(self._hwnd, win32con.WM_CLOSE, 0, 0) # kill it
sleep(0.5) # important to let time for the window to be closed
Call this method just after cW = cWindow().
Another bug trap is to prevent this exception in SetAsForegroundWindow:
error: (0, 'SetForegroundWindow', 'No error message is available')
just send an alt key before the win32gui call:
# Add this import
import win32com.client
# Add this to __ini__
self.shell = win32com.client.Dispatch("WScript.Shell")
# And SetAsForegroundWindow becomes
def SetAsForegroundWindow(self):
self.shell.SendKeys('%')
win32gui.SetForegroundWindow(self._hwnd)
Last, if I may, do not compare != None but is not None. More pythonic ;)
This is the full code:
# coding: utf-8
import re, traceback
import win32gui, win32con, win32com.client
from time import sleep
class cWindow:
def __init__(self):
self._hwnd = None
self.shell = win32com.client.Dispatch("WScript.Shell")
def BringToTop(self):
win32gui.BringWindowToTop(self._hwnd)
def SetAsForegroundWindow(self):
self.shell.SendKeys('%')
win32gui.SetForegroundWindow(self._hwnd)
def Maximize(self):
win32gui.ShowWindow(self._hwnd, win32con.SW_MAXIMIZE)
def setActWin(self):
win32gui.SetActiveWindow(self._hwnd)
def _window_enum_callback(self, hwnd, wildcard):
'''Pass to win32gui.EnumWindows() to check all the opened windows'''
if re.match(wildcard, str(win32gui.GetWindowText(hwnd))) is not None:
self._hwnd = hwnd
def find_window_wildcard(self, wildcard):
self._hwnd = None
win32gui.EnumWindows(self._window_enum_callback, wildcard)
def kill_task_manager(self):
wildcard = 'Gestionnaire des t.+ches de Windows'
self.find_window_wildcard(wildcard)
if self._hwnd:
win32gui.PostMessage(self._hwnd, win32con.WM_CLOSE, 0, 0)
sleep(0.5)
def main():
sleep(5)
try:
wildcard = ".*Building Operation WorkStation.*"
cW = cWindow()
cW.kill_task_manager()
cW.find_window_wildcard(wildcard)
cW.BringToTop()
cW.Maximize()
cW.SetAsForegroundWindow()
except:
f = open("log.txt", "w")
f.write(traceback.format_exc())
print(traceback.format_exc())
if __name__ == '__main__':
main()
Sources: how do I close window with handle using win32gui in Python and win32gui.SetActiveWindow() ERROR : The specified procedure could not be found.
Note: The following deals only with making sure that always-on-top windows such as Task Manager are hidden before activating the window - it assumes that the activation part itself works fine, which may not be the case. The conditions under which a process is allowed to call the SetForegroundWindow Windows API function are listed here.
Task Manager is special in two respects:
By default, it is set to display always on top, i.e., above all other windows.
Even when that is turned off (Options > Always on Top unchecked), you can still make it display on top of other always-on-top windows (something that ordinary windows seemingly cannot do).
Your code:
is working - in my tests - in the sense that the target window does become the active window.
is not working in the sense that the Task Manager window still stays on top of the (maximized) window.
even trying to make your window an always-on-top window as well wouldn't help, unfortunately.
Specifically checking for the presence of the Task Manager window and minimizing it is an option, but note that there may be other always-on-top windows, so for a robust solution you have to identify all open always-on-top windows and minimize them:
The following tries hard to identify all always-on-top windows except the Task Bar and Start button, and minimizes (effectively hides) any such windows.
The new methods are hide_always_on_top_windows and _window_enum_callback_hide.
import win32gui, win32con
import re, traceback
from time import sleep
class cWindow:
def __init__(self):
self._hwnd = None
def SetAsForegroundWindow(self):
# First, make sure all (other) always-on-top windows are hidden.
self.hide_always_on_top_windows()
win32gui.SetForegroundWindow(self._hwnd)
def Maximize(self):
win32gui.ShowWindow(self._hwnd, win32con.SW_MAXIMIZE)
def _window_enum_callback(self, hwnd, regex):
'''Pass to win32gui.EnumWindows() to check all open windows'''
if self._hwnd is None and re.match(regex, str(win32gui.GetWindowText(hwnd))) is not None:
self._hwnd = hwnd
def find_window_regex(self, regex):
self._hwnd = None
win32gui.EnumWindows(self._window_enum_callback, regex)
def hide_always_on_top_windows(self):
win32gui.EnumWindows(self._window_enum_callback_hide, None)
def _window_enum_callback_hide(self, hwnd, unused):
if hwnd != self._hwnd: # ignore self
# Is the window visible and marked as an always-on-top (topmost) window?
if win32gui.IsWindowVisible(hwnd) and win32gui.GetWindowLong(hwnd, win32con.GWL_EXSTYLE) & win32con.WS_EX_TOPMOST:
# Ignore windows of class 'Button' (the Start button overlay) and
# 'Shell_TrayWnd' (the Task Bar).
className = win32gui.GetClassName(hwnd)
if not (className == 'Button' or className == 'Shell_TrayWnd'):
# Force-minimize the window.
# Fortunately, this seems to work even with windows that
# have no Minimize button.
# Note that if we tried to hide the window with SW_HIDE,
# it would disappear from the Task Bar as well.
win32gui.ShowWindow(hwnd, win32con.SW_FORCEMINIMIZE)
def main():
sleep(5)
try:
regex = ".*Building Operation WorkStation.*"
cW = cWindow()
cW.find_window_regex(regex)
cW.Maximize()
cW.SetAsForegroundWindow()
except:
f = open("log.txt", "w")
f.write(traceback.format_exc())
print(traceback.format_exc())
main()

get window handler from started process

I see there's win32process.GetWindowThreadProcess() that gets a window handler and returns it's process id. Is there a way to do the opposite: get the window handler of a running process by it's process id? Something like win32gui.GetWindowHandler(processId) ?
Specifically What I'm trying to do:
I have a python script that runs an external program, lets say notepad.exe.
Notepad is fired when runProgram() method is called. I want to prevent this method from running Notepad more than once. I accomplish this in the following way, using win32process:
import win32process as process
import sys
PORTABLE_APPLICATION_LOCATION = "C:\\Windows\\system32\\notepad.exe"
processHandler = -1
def runProgram():
global processHandler
#don't run a process more than once
if (isLiveProcess(processHandler)):
#Bring focus back to running window!
return;
try:
startObj = process.STARTUPINFO()
myProcessTuple = process.CreateProcess(PORTABLE_APPLICATION_LOCATION,None,None,None,8,8,None,None,startObj)
processHandler = myProcessTuple[2]
except:
print(sys.exc_info[0])
def isLiveProcess(processHandler): #Process handler is dwProcessId
processList = process.EnumProcesses()
for aProcess in processList:
if (aProcess == processHandler):
return True
return False
runProgram()
This works as expected, but if the process is found to be already alive, I'd like to bring it's window back to front with win32gui
I dont think that Windows API provides a method for this , but you could iterate over all open windows , and find the one that belongs to you .
I have modified your program so it looks like this :
import win32process
import win32process as process
import win32gui
import sys
PORTABLE_APPLICATION_LOCATION = "C:\\Windows\\system32\\notepad.exe"
processHandler = -1
def callback(hwnd, procid):
if procid in win32process.GetWindowThreadProcessId(hwnd):
win32gui.SetForegroundWindow(hwnd)
def show_window_by_process(procid):
win32gui.EnumWindows(callback, procid)
def runProgram():
global processHandler
#don't run a process more than once
if (isLiveProcess(processHandler)):
#Bring focus back to running window!
show_window_by_process(processHandler)
return;
try:
startObj = process.STARTUPINFO()
myProcessTuple = process.CreateProcess(PORTABLE_APPLICATION_LOCATION,None,None,None,8,8,None,None,startObj)
processHandler = myProcessTuple[2]
except:
print(sys.exc_info[0])
def isLiveProcess(processHandler): #Process handler is dwProcessId
processList = process.EnumProcesses()
for aProcess in processList:
if (aProcess == processHandler):
return True
return False
runProgram()

Python program as Windows Service

below is my code that I am trying to turn into a windows service. You'll see test.py as the call it makes and all this is a short script that writes into a log file (as a test).
The code is there to make it a windows service and it does that fine, but when I run it nothing writes into the log file. Help greatly appreciated. Below is the code:
import win32service
import win32serviceutil
import win32api
import win32con
import win32event
import win32evtlogutil
import os, sys, string, time
class aservice(win32serviceutil.ServiceFramework):
_svc_name_ = "MyServiceShortName"
_svc_display_name_ = "A python test"
_svc_description_ = "Writing to a log"
def __init__(self, args):
win32serviceutil.ServiceFramework.__init__(self, args)
self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
def SvcStop(self):
self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
win32event.SetEvent(self.hWaitStop)
def SvcDoRun(self):
import servicemanager
servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,servicemanager.PYS_SERVICE_STARTED,(self._svc_name_, ''))
self.timeout = 1000 #1 seconds
# This is how long the service will wait to run / refresh itself (see script below)
while 1:
# Wait for service stop signal, if I timeout, loop again
rc = win32event.WaitForSingleObject(self.hWaitStop, self.timeout)
# Check to see if self.hWaitStop happened
if rc == win32event.WAIT_OBJECT_0:
# Stop signal encountered
servicemanager.LogInfoMsg("SomeShortNameVersion - STOPPED!") #For Event Log
break
else:
#what to run
try:
file_path = "test.py"
execfile(file_path)
except:
pass
#end of what to run
def ctrlHandler(ctrlType):
return True
if __name__ == '__main__':
win32api.SetConsoleCtrlHandler(ctrlHandler, True)
win32serviceutil.HandleCommandLine(aservice)
Edit: Thought for the sake of it I'd include my test.py file's code, it has unnecessary imports but will get the job done if you run it alone.
import win32service
import win32serviceutil
import win32api
import win32con
import win32event
import win32evtlogutil
import os
logfile = open("log.txt", "a") #open file to log restart timestamp
logfile.write("\nthat's good!!!!")
logfile.close()
Okay so I figured it out and would like to come back and post in case anyone else is dealing with this, all though this was a tad unique.
You have to specify your file path if you are within a windows service, duh... but it wasn't done and I pulled my hair out for no reason.
file_path = "test.py"
should have been
file_path = r"c:\users\...\test.py"
Be careful when using '\' for windows file paths. They must be escaped like '\\' or the string must be declared as raw string ('r'). Using the unix like slash '/' separators works also but may look odd for windows users.

Python Unittest: Open and wait until the program is closed

Currently I try to create an unit test which opens a file (with the corresponding application) and then the test-run should wait until the program is closed.
def test_HFG(self):
#....
print "please edit this file"
os.chdir(r'C:\test\a')
os.startfile("myfile.vdx")
# here I need a "stop until the program is closed"-function
#....
Does anyone have any idea how to realize(as simple as possible) my plan?
os.startfile is, of course, completely non-blocking with no options to wait.
I'd recommend using the subprocess module, calling the Windows "start" command to open the file with the associated object, which does the same thing as os.startfile, but allows you to wait for the process to finish.
e.g.:
subprocess.call(["start", my_file])
From the docs:
startfile() returns as soon as the associated application is
launched. There is no option to wait for the application to close, and
no way to retrieve the application’s exit status.
If you know the path of the application to open the file with, you could use subprocess.Popen() which allows for you to wait.
See:
http://docs.python.org/library/os.html#os.startfile
http://docs.python.org/library/subprocess.html#subprocess.Popen
The documentation of os.startfile explicitly says:
startfile() returns as soon as the associated application is launched.
There is no option to wait for the application to close, and no way to
retrieve the application’s exit status
So, I recommend using an alternative method, such as launching it via subprocess.Popen, which does allow you to wait until the sub-process finishes.
answer = raw_input("Please Edit this file (done): ")
if answer == done:
blablabla
else:
stop programm or whatever
just let him tell you when he is done, simplest way i can imagine
You can call the underlying windows APIs, as recommended in this C++ answer, either via pywin32:
def start_file_wait(fname):
import win32con
import win32api
import win32event
from win32com.shell import shellcon
from win32com.shell.shell import ShellExecuteEx
rc = ShellExecuteEx(
fMask=shellcon.SEE_MASK_NOCLOSEPROCESS,
nShow=win32con.SW_SHOW,
lpFile=fname)
hproc = rc['hProcess']
win32event.WaitForSingleObject(hproc, win32event.INFINITE)
win32api.CloseHandle(hproc)
or directly from ctypes:
def startfile_wait(fname):
import ctypes
from ctypes.wintypes import ULONG, DWORD, HANDLE, HKEY, HINSTANCE, HWND, LPCWSTR
class SHELLEXECUTEINFOW(ctypes.Structure):
_fields_ = [
("cbSize", DWORD),
("fMask", ULONG),
("hwnd", HWND),
("lpVerb", LPCWSTR),
("lpFile", LPCWSTR),
("lpParameters", LPCWSTR),
("lpDirectory", LPCWSTR),
("nShow", ctypes.c_int),
("hInstApp", HINSTANCE),
("lpIDList", ctypes.c_void_p),
("lpClass", LPCWSTR),
("hkeyClass", HKEY),
("dwHotKey", DWORD),
("DUMMYUNIONNAME", ctypes.c_void_p),
("hProcess", HANDLE)
]
shell_execute_ex = ctypes.windll.shell32.ShellExecuteExW
shell_execute_ex.argtypes = [ctypes.POINTER(SHELLEXECUTEINFOW)]
shell_execute_ex.res_type = ctypes.c_bool
wait_for_single_object = ctypes.windll.kernel32.WaitForSingleObject
wait_for_single_object.argtypes = [HANDLE, DWORD]
wait_for_single_object.res_type = DWORD
close_handle = ctypes.windll.kernel32.CloseHandle
close_handle.argtypes = [HANDLE]
close_handle.res_type = bool
# https://stackoverflow.com/a/17638969/102441
arg = SHELLEXECUTEINFOW()
arg.cbSize = ctypes.sizeof(arg)
arg.fMask = 0x00000040 # SEE_MASK_NOCLOSEPROCESS
arg.hwnd = None
arg.lpVerb = None
arg.lpFile = fname
arg.lpParameters = ""
arg.lpDirectory = None
arg.nShow = 10 # SW_SHOWDEFAULT
arg.hInstApp = None
ok = shell_execute_ex(arg)
if not ok:
raise ctypes.WinError()
try:
wait_for_single_object(arg.hProcess, -1)
finally:
close_handle(arg.hProcess)

Categories

Resources