Win32API commands seem not to work with PowerShell (I'm running 7, but I assume unimportant), only with the inferior IMHO Command Prompt.
I am building a program (a glorified HOSTS site blocker) that runs on the simple structure of "query command, execute command; repeat until user prompts to exit" and one of the things the user can query the program with is UNBLOCK category>site_nickname FOR minutes
. This runs the program in one thread, starts a timer in another thread so the user can keep using the program as they desire. After the timer, the UNBLOCK command the program ran at start is undone so the user can get back to work. What I want to avoid is the user being able to cheat fate by saying UNBLOCK, then closing the program via the 'close' button, terminating the PowerShell instance, my Python program, and all its threads and thus ensuring the UNBLOCK command is never undone with a partner BLOCK command.
The user can exit the program by typing EXIT or CANCEL. This has the program wrap up, and then run sys.exit()
. As I discovered, using the atexit
library just basically does that but runs the function you want afterwards, does not intercept a close-button click. And setting the console control handler only seems to work in Command Prompt (whose support for ANSI escapes/emojis/Unicode probably too, seems to be spotty), also, the window_exit()
function, or I guess the proper term is "method" --
def window_exit(signal_type):
sure = ask_input("Wait, wait! Are you sure you want to exit?") # input plus ANSI escape sequence, highlights the input prompt in blue and adds ">>" on a new line
if sure == "Yes":
evaluate("EXIT") # runs this command as if the user typed it in to be evaluated by my program
-- does not accept input properly. Instead, it displays the message and then for some reason decides I am trying to pull some "Press any key to continue ..."
-type stuff, when I want the user to be able to type whatever and then have it be evaluated.
What can I do so any attempt to "cheat" and exit the program early is acknowledged and dealt with?
CodePudding user response:
In Python, there is no direct equivalent to the win32api.SetConsoleCtrlHandler() function that works in PowerShell. However, you can achieve similar functionality using the signal module.
The signal module allows you to register a function to be called when a specific signal is received by the program. In Windows, the CTRL_C_EVENT signal is sent when the user presses the CTRL C keys. You can register a function to handle this signal using the signal.signal() function.
Here is an example of how you can register a function to handle the CTRL_C_EVENT signal in Python:
import signal
def handle_ctrl_c(signum, frame):
print("CTRL C pressed")
signal.signal(signal.SIGINT, handle_ctrl_c)
In this example, the handle_ctrl_c function will be called when the CTRL C keys are pressed. The signum argument is the signal number that was received, and the frame argument is the current stack frame.
-- EDITED
To detect when the user clicks the graphical close button you can use the SetWindowLong function to set the window procedure for a window and then use the WNDPROC callback function to handle the WM_CLOSE message, which is sent when the close button is clicked.
Example --
def close_handler(hwnd, msg, wparam, lparam):
if msg == win32con.WM_CLOSE:
# Handle the close button being clicked here
pass
# Set the window procedure for the window, and specify close_handler
old_wndproc = win32api.SetWindowLong(hwnd, win32con.GWL_WNDPROC, close_handler)
# If needed, save the old window procedure to call later
win32api.SetWindowLong(hwnd, win32con.GWL_USERDATA, old_wndproc)