C# catch kill command - windows

how can I catch windows taskkill command in order to prevent it?

You cannot prevent your process being killed. The only way to keep a program alive is to have a second Watchdog application that is constantly pooling that process to ensure it's running.
So, you have two Applications; AppA (Main) and AppB (Watchdog).
AppA checks if AppB is running. If
not, AppA starts AppB.
AppB checks if AppA is running. If
not, AppB starts AppA.
But this is usually a design for a malicious process, so I hope you're not doing anything untoward.
You can see the following events in the message queue when End process is clicked:
WM_CLOSE // UI app
CTRL_CLOSE_EVENT //
Console app
But if your application does not close in a timely manner, then the kill command will be sent, which cannot be captured.

I'm pretty sure it is not possible, otherwise a single application could stop windows from ever shutting down. Even when the process is hung, killing it in task manager eventually works. If it was possible, malicous software, etc would probably have a hey-day using it - not only could they take control of various parts of your PC, they'd make sure you could never get it back again.

Related

How to keep a user process running until Windows logoff is definite?

I have an application that is running on Windows, in the user's session, that I don't want the user to be able to close by accident.
One way the user can close it is by having unsaved data (e.g. in notepad) and start the process of logging off. Notepad rejects the WM_QUERYSESSION message; Windows prompts the user that there is unsaved data; and the user gets to cancel the logoff.
Other applications (including mine), get the WM_QUERYSESSION, respond with TRUE, then get WM_ENDSESSION, and quit. Importantly, they quit before Windows has even decided to prompt the user about unsaved data in notepad.
If the user cancels the logoff, the end result is that the user's session continues without all the processes that honoured the end session messages.
What I'm trying to find a way of doing is keeping my process running until we're past the point that the user could cancel the logoff. Looking at the microsoft docs on this, I don't see an obvious way of doing that - each process goes through its own WM_QUERYSESSION > WM_ENDSESSION, and the docs are explicit that this happens for each application independently.
I don't want to reply to WM_QUERYSESSION with FALSE, as I don't want to block the logoff myself, just stay running if something else blocks it.
Are there any other ways of finding out when Windows has decided that all the WM_QUERYSESSION messages were replied to with TRUE, and the logoff is inevitable?
(I think this is a Windows question, rather than a question specific to the language I'm using, but in case it matters, it's PureBasic. Any Win32 API approach should be workable though.)
If any app returns FALSE to WM_QUERYENDSESSION, apps that had already returned TRUE will receive WM_ENDSESSION with wParam=FALSE to indicate shutdown has been canceled.
If all apps return TRUE to WM_QUERYENDSESSION, only then will they receive WM_ENDSESSION with wParam=TRUE to indicate shutdown is proceeding.
See Application Shutdown Changes in Windows Vista and Restart Manager: Guidelines for Applications for more details of how WM_QUERYENDSESSION and WM_ENDSESSION work.
Is your app paying attention to the wParam value given by WM_ENDSESSION? Or does it just blindly exit unconditionally when it receives WM_ENDSESSION? Not all apps pay attention like they should be. Make sure yours does.
Update: Per the WM_QUERYENDSESSION documentation, and the Logging Off documentation:
When an application returns TRUE for WM_QUERYENDSESSION, it receives the WM_ENDSESSION message and it is terminated, regardless of how the other applications respond to the WM_QUERYENDSESSION message.
So, there is really nothing your app can do here. Once it responds TRUE to WM_QUERYENDSESSION, that is it, game over. Your app will receive WM_ENDSESSION and be forcibly terminated if it does not exit within a few seconds, regardless of how other apps respond to the shutdown.
So, the only way I can think of to really detect when the session is actually ending is to use a service instead, as a service can receive SERVICE_CONTROL_SHUTDOWN and SERVICE_CONTROL_SESSIONCHANGE notifications.

Should I process WM_ENDSESSION, WM_QUERYENDSESSION, both or neither?

If a system is trying to shut down, an app can block this shutdown by overriding OnQueryEndSession() and returning FALSE. Surely that means WM_ENDSESSION is the only definitive message to respond to regarding shutdown.
On the other hand, the top answer to this question quotes no less than Raymond Chen as saying that responding to WM_ENDSESSION is essentially pointless. So this is confusing.
Is there some kind of "best practice" principles to apply in deciding which of these messages (if any) one should respond to for doing what kinds of application shutdown work?
In particular, if neither message is handled, will a shutdown process cause an application to be closed as if the user had closed the application manually (e.g. click on red X close button)?
This article from Microsoft gives a very comprehensive discussion of end-of-session best practice both pre- and post-Vista. The article makes it quite clear that one should assume that if one receives a WM_QUERYENDSESSION then shutdown will occur at some point.
As soon as all applications have responded to the WM_ENDSESSION message, or been forced to terminate within 5 seconds of receiving the WM_ENDSESSION message, Windows may shut down at any time. This may limit what can be done in response to WM_ENDSESSION.
If an application requires more time to clean itself up:
If your application may need more than 5 seconds to complete its shutdown processing in response to WM_ENDSESSION, it should call ShutdownBlockReasonCreate() in its WM_QUERYENDSESSION handler, and promptly respond TRUE to WM_QUERYENDSESSION so as not to block shutdown. It should then perform all shutdown processing in its WM_ENDSESSION handler.
Windows will apparently not send any additional messages to your application to allow it to exit "gracefully" (e.g. WM_CLOSE). Rather, it will simply call TerminateProcess. If you want a graceful close, you have to build it yourself within the above constraints.
You do need to close down your application in WM_ENDSESSION, at least if you want to support the Restart Manager API. I think both MSDN and Raymond are wrong here. (Maybe it changed recently, or they overlooked the Restart Manager?)
The Restart Manager API is used by installers to close and restart exes which have files locked that they need to replace. To support being restarted by it, you call RegisterApplicationRestart and then need to have a window which handles WM_QUERYENDSESSION and WM_ENDSESSION.
If you don't shut down your app in the WM_ENDSESSION handler than it will simply keep running and block the Restart Manager, and in turn the installers trying to use it.
I found this out the hard way. MSDN explicitly says you don't need to call PostQuitMessage, but if I don't do that then my process keep running.
I suspect the documentation didn't realise the Restart Manager is different, and less forceful, compared to what happens when the entire OS shuts down.
(Edit: I should add, this was with a simple ATL COM EXE server, but as far as I can tell there was nothing about that complicating things, and Windows simply wasn't triggering a WM_QUIT to the message loop unless I did it myself.)

In Windows 7, how to send a Ctrl-C or Ctrl-Break to a separate process

Our group has long running processes which run daily. The processes are typically started at 9pm on any given day and run until 7pm the next day. Thus they typically run 22hrs/day. They are started by scheduled tasks on servers under a particular generic user ID, and they start and run regardless of whether or not that user ID is logged on. Thus, they are windowless console executables.
The tasks orchestrate computations running on a large server farm. Generally these controlling tasks run uninterrupted for the full 22hrs/day. However, we often have a need to stop and restart these processes. Because they control a multitude of tasks running on our server farm, it is important that they be shut down cleanly, so that they can stop and shut down all the server farm processes. Which brings me to our problem.
The controlling process has been programmed to respond to ctrl-C and ctrl-break signals. This works fine when the process is manually started in a console where we have access to the console and can "type" ctrl-c or ctrl-break in the console window. However, as mentioned, the processes typically run as windowless scheduled tasks. Hence we cannot "type" anything into a non-existent console window. Because they are console processes that execute without a logon process, the also must be able to execute in a completely windowless environment. So, how do we set up the process to listen for a shut-down signal?
While the process does indeed listen for a ctrl-C and ctrl-break signal, I can see no way to send that signal to a process. This seems to be a fundamental problem in Windows, or am I wrong? I am aware of SendSignal.exe, but so far have been unable to get it to work. It fails as follows:
>SendSignal 26320
Sending signal to process 26320...
CreateRemoteThread failed with 0x00000005.
StartRemoteThread failed with 0x00000005.
0x00000005 == Access is denied.
Trying "taskkill" without -F results in:
>taskkill /PID 24840
ERROR: The process with PID 24840 could not be terminated.
Reason: This process can only be terminated forcefully (with /F option).
All other "kill" functions kill the process immediately rather than sending a signal.
One possible solution would be a file-watch based solution: create a watch for some modification of a specific file. But this is a hack and we would prefer to do it with appropriate signaling. Has anyone solved this issue? It seems to be so very basic a functionality, and it is certainly trivial to do it in a Unix environment. Surely Microsoft has provided SOME mechanism to allow clean shut down of a windowless executable?
I am aware of the thread below, whose question is virtually identical (save for the specification of why the answer is necessary, i.e. why one needs to be able to do this for a windowless, console-less process), but there is no answer there excpet for "use SendSignal", which, as I said, does not work for us:
Can I send a ctrl-C (SIGINT) to an application on Windows?
There are other similar questions, but no answers as yet.
Any help appreciated.
[Upgrading #Anon's comment to an answer for visibility]
windows-kill worked perfectly and managed to resolve access denial issues faced with SendSignal. A privileged user would have to run it as well of course.
windows-kill also supports both ctrl-c and ctrl-break signals.

Can I handle the killing of my windows process through the Task Manager?

I have a windows C++ application (app.exe). When the app is closed, I need to perform some cleanup tasks specific to my application. What happens when this process (app.exe) is killed through the Task Manager. Assuming that the application is still responsive, can I somehow handle this situation in my app.exe?
I am looking for something similar to how kill <pid> in Linux will send the SIGTERM signal to the process indicated by pid. I could then register my own signal handler for SIGTERM and perform the cleanup.
There are two ways to kill application in Task Manager.
Killing through Applications tab would roughly be equivalent of SIGTERM. Application may intercept it and do more processing, since it's basically sending a "close window" message. Message to catch is WM_CLOSE.
Killing through Processes tab would roughly be equivalent of SIGKILL. There is nothing you can do to intercept that, short of monitoring user's actions in Task Manager's listbox and End Process button, or having a watchdog process that will see when the first one is killed.
Alternatively, design the application in a way that does not require cleanup, or in a way that it will perform cleanup at startup.
I think you will need another PID that is monitoring the PID of your app.exe and does the necessary work at the time.
That depends, if the user chooses to "End Task" your application you will be notified and you can handle it see this.
but if the user chooses to end the process, you have no way to handle it in your application. the easiest way would be a second process or you can inject into process manager and hook the TerminateProcess API.

How to abort shutdown in Windows (XP|Vista) programatically?

I want to be able to 1. detect (and, if needed 2. abort) OS shutdown from my application, preferably by using the Windows API.
I know that it is possible to abort shutdown manually using the command shutdown -a In the worst case, I could ShellExecute this, but I was wondering if there was a better way to prevent the shutdown programatically.
Maybe it would be enough to be notified programatically that the OS is about to shut down - how to do this?
From MSDN:
The WM_QUERYENDSESSION message is sent when the user chooses to end the session or when an application calls one of the system shutdown functions. If any application returns zero, the session is not ended. The system stops sending WM_QUERYENDSESSION messages as soon as one application returns zero.
So, my application's WindowProc now processes the WM_QUERYENDSESSION message and returns 0.
Didn't expect it to be this simple; as a bonus, it also works on Windows 2000.
In regards to 'simply' returning 0 to block a shutdown, it isn't as simple as that if you want to do it in the proper way. Especially on Vista. For example please also read http://msdn.microsoft.com/en-us/library/ms700677(VS.85).aspx

Resources