In Python 3.10.5 on Windows 11 using the win32gui module, I want to create a simple window switching application. First, I make a list of hwnds of all the running windows and then elsewhere in the code I switch to one of those windows using the given hwnd. The relevant and simplified parts of the code look like this:
def winEnumHandler(hwnd, ctx):
if win32gui.IsWindowVisible(hwnd):
windows.append(hwnd)
def switchToWindow(hwnd):
win32gui.SetForegroundWindow(hwnd)
def main():
windows = []
win32gui.EnumWindows(winEnumHandler, None)
main()
The code works without an issue if my Python application built using the wxPython module is in the foreground and when I want to switch to a window other than my Python application, but whenever, having another application in the foreground, I want to switch back to the main frame of my application or to the Windows command line from which I am running the Python application, I get the following error:
Exception in thread Thread-2 (showSwitcher):
Traceback (most recent call last):
File "C:\Users\asamec\AppData\Local\Programs\Python\Python310-32\lib\threading.py", line 1016, in _bootstrap_inner
self.run()
File "C:\Users\asamec\AppData\Local\Programs\Python\Python310-32\lib\threading.py", line 953, in run
self._target(*self._args, **self._kwargs)
File "c:\Users\asamec\Dropbox\DIY\Python\WinSwitcher\WinSwitcher\src\WinSwitcher.py", line 207, in showSwitcher
self.switchToApp(app)
File "c:\Users\asamec\Dropbox\DIY\Python\WinSwitcher\WinSwitcher\src\WinSwitcher.py", line 165, in switchToApp
self.switchToWindow(hwnd)
File "c:\Users\asamec\Dropbox\DIY\Python\WinSwitcher\WinSwitcher\src\WinSwitcher.py", line 172, in switchToWindow
win32gui.SetForegroundWindow(hwnd)
pywintypes.error: (5, 'SetForegroundWindow', 'Access is denied.') t
So the questions are: how can I bypass the "Access is denied" exception, and why is it thrown in the case of switching only from another window to my Python application window running in the background, not when switching from my application window in the foreground to other windows?
Update
Based on the first anser provided for this post, it looks like due to the Windows system restrictions the needed window switching is not possible using the win32gui module and its APIs. Then the question is: is there another way how to switch to a specific window even when the Python app is not running in the foreground? I am asking because such switching is actually possible using the pywinauto Python module if the process PID is known, with the following code:
from pywinauto import Application
app = Application().connect(process=pid)
app.top_window().set_focus()
My original reason for not wanting to use the above code employing the pywinauto module was that I thought it is performing slowly, however, I have found out that the performance issue was in some other part of the code. Therefore I am marking the first ansewr to this question as the accepted one, because it also answers my follow-up question, which was: why was it that the pywinauto method was not affected by the Windows system restrictions?
The accepted anser provides a solution which does not require the PID of the desired application and related pywinauto methods for switching to that application. Instead, it provides a solution for switching to the desired window rather than aplication via the window's hwnd, which was actually the original intent of the question. The answer also explains that the workaround for bypassing the Windows system window switching restrictions lies in the usage of the tricck of moving the mouse pointer out of the screen before running the win32gui.SetForegroundWindow(hwnd)
method.