[python-win32] Unable to detect shutdown
Eryk Sun
eryksun at gmail.com
Wed Mar 9 17:28:34 EST 2022
On 3/9/22, H.Fujii <hisabojp at gmail.com> wrote:
> I'm currently developing a console program in Python 3.9.
> I want to detect the shutdown of Windows and save the data to a file
> safely.
> I created a sample program by referring to the following URL.
> https://docs.microsoft.com/en-us/windows/console/registering-a-control-handler-function
>
> However, the sample program does not detect shutdown
> (CTRL_SHUTDOWN_EVENT) well.
Console control events are sent by the Windows session server,
csrss.exe, by creating a thread in the target process that starts at
CtrlRoutine() in kernelbase.dll. This includes the cancel (i.e.
Ctrl+C), break, and close events that are requested by a console
session host (i.e. conhost.exe or openconsole.exe), as well as the
system-initiated logoff and shutdown events.
The session server sends the logoff and shutdown events to any process
that isn't a GUI process. It doesn't matter whether or not the process
is attached to a console. For example, the service control manager in
services.exe depends on the console shutdown event, even though it is
not a console application and is not attached to a console.
A GUI process is one that's connected to a window station (e.g.
interactive "WinSta0"), with one or more threads connected to a
desktop (e.g. "WinSta0\Default"). Loading user32.dll, directly or
indirectly, connects the process and loading thread to a window
station and desktop (e.g. as set by its STARTUPINFO). In order to
avoid getting converted to a GUI process, a console or background
application has to carefully restrict itself to the base API, avoiding
anything that might end up loading user32.dll, or by spawning a child
process to call anything that loads user32.dll as a remote procedure
call.
Python 3.9+ starts out okay in this regard. But some extension modules
in the standard library -- e.g. _ssl.pyd, _hashlib.pyd, and
_ctypes.pyd -- do not delay-load dependencies that end up loading
user32.dll. Thus, for example, it is currently impossible to use
ctypes to handle the console logoff and shutdown events.
As to win32api, it directly depends on user32.dll as well as
indirectly via other DLLs. I think partitioning out a win32base module
would be a worthy goal, but that's up to the PyWin32 project
developers.
If you can't take the simple route of using console logoff and
shutdown events, then all you can do is fully embrace being a GUI
process. Create a hidden top-level window with a message loop that
handles WM_QUERYENDSESSION [1] and WM_ENDSESSION [2].
---
[1] https://docs.microsoft.com/en-us/windows/win32/shutdown/wm-queryendsession
[2] https://docs.microsoft.com/en-us/windows/win32/shutdown/wm-endsession
More information about the python-win32
mailing list