Executing a program before System Shutdown - c#

I have a program I need to run before a system shutdown executes. This means, before any program gets terminated because of the shutdown, I need to execute said program, ideally via Process.Start().
Initially I tried executing said program in the Windows Shutdown Scripts, however that script is only executed after programs have already been terminated. I however need to terminate some running applications in the right order.
I have tried the event SystemEvents.SessionEnding and SessionEnded, but this event does not let you wait for more than 1-2 seconds, and the cancelling of the shutdown is not possible either.
I got up to this example where, in the WndProc event about shutdown I would execute a Process. I reach the Event, I reach the point where I can actually pause the shutdown process. However, when I try to actually call a process, I get the "0xC0000142" error.
A search for this resulted in one option being that the user is incorrect, however I want to call this application with the user that is running the executing program. The other option was that the environment path was wrong. I set an environment path for the second option, but in my opinion, I shouldn't need to change anything for the first option, since I want to execute it with the current user.
A third possibility I thought about might be that at this state of the system shutdown, no new processes can be spawned.
What can I do to fix this and actually execute the program here? I seem to be out of ideas at this point.
Clarification:
The "cleanup" program needs to shut down programs in a given order. The programs to be shut down are our own, but Windows Forms (the only way I can see that can use a shutdown handler) cannot be used there.
Program A is the one that handles the OnShutdown. Program A, on Shutdown, will call Program B, which does the ordered closing of programs. Program B, in my solution (that includes Forms) cannot be launched and returns an error, as specified in paragraph 4. The only user interaction here would be a user pressing a power button leading to system shutdown, or a remotely executed "shutdown.exe" call.

Related

Prevent windows server from suspending my process

I've developed a program (winforms application, not a service) in C# that runs on a windows server.
The program starts multiple times based on requests from outside the server.
From time to time I see that the program is "Suspended" for an unknown reason. I think it is related to a lack of resources, but not sure.
How can I prevent windows from suspending my program?
Update
To be clear, I know that the program crash and it is OK. What I'm asking is not how to improve performance \ prevent the crash, but how to remove the process from the process list \ prevent this suspended status?
Depends in your hardware/software configuration, it's hard to know where is your bottleneck.
I recommend instead to do Multi-thread/task app where you're able to control threads and asign priority, resources, stop, resume, abort, etc...
use on command console to start and check if happends the same but with the parameter high:
start /HIGH <ProgramPath>
Read more how to change priority on executables
Task Scheduler on windows servers MSDN -> Priority
(It's only an opinion, start digging about others solutions.)
You must set the ServiceBase.CanPauseAndContinue Property to False in the constructor of the service before it is started.
NOTE the side effect is:
If CanPauseAndContinue is false, the SCM will not pass Pause or
Continue requests to the service, so the OnPause and OnContinue
methods will not be called even if they are implemented. In the SCM,
the Pause and Continue controls are disabled when CanPauseAndContinue
is false.
For more information see this Microsoft Doc
There are multiple methods of keeping an app awake.
One method would be to request a deferral and then only mark that deferral complete when you are done.
First you need a deferral object that will remain in scope of your process
SuspendingDeferral deferral
Then you need to override OnSuspending
async protected void OnSuspending(object sender, SuspendingEventArgs args)
{
deferral = args.SuspendingOperation.GetDeferral();
await SuspensionManager.SaveAsync();
}
Then you need to mark the deferral complete when your process is done doing whatever it was doing
if (deferral is not null) { deferral.Complete(); }
Full details can be found in the Microsoft docs
For discussion of other methods see this thread:
How to Disable UWP App Suspension?
Technically the process is suspended but if you look at the memory consumption of 32K you can tell it was not suspended. Your process did crash with an unhandled exception which in turn triggers Windows Error Reporting to take a memory dump.
This involves some kernel magic which keeps a process handle in the kernel (System process) alive. It is not a big deal or memory leak since the process did already terminate. Only the PEB (Process Environment Block) the 32K which includes mostly command line, loaded dlls and environment variables are still there.
I would not worry about suspended processes but why your process did crash with an unhandled exception. This could even be a feature to make programers aware that their process did crash by looking at a looong list of suspended processes in Task Manager ;-).
Since it is a .NET Application you will find a generic error messages that a process did crash in the Application event log and a .NET Runtime logged error message with more exception details.
Perhaps that is already enough to keep you going to fix your issue. If not you can configure WER to create a full memory dump via a registry setting (https://learn.microsoft.com/en-us/windows/win32/wer/collecting-user-mode-dumps). Now you have for each "suspended" process a full memory dump you can load into Visual Studio to look further what was the issue.
To further check who holds your process handle still open you can use handle e.g. ProcessHacker (the better Process Explorer) https://processhacker.sourceforge.io/nightly.php
If something else is happening you can see with this tool who is holding any outstanding handles to your process open. But I strongly suspect it is the Windows Kernel.

Kill Multithreaded Process

Windows Mobile 6.5
I have a process which uses System.Threading.Timer upload some data to net at specified intervals.
Now I want to terminate this process from a GUI application. I can use process enumerator to get Process object. What happens when I call Process.Kill? Does it jsut terminate it, the process could be in the middle of reading/deleting data from local database and sending it to service. What can I do make sure that atleast if its in middle it does not terminate and once it is done it can terminate before next Timer event fires?
Terminating an application like that cuts it off at the knees, introducing the distinct possibility of corrupting data. The only way around that is to not terminate the process.
You'll have to introduce a way to communicate to the application that it need to exit so that it can finish whatever it's doing so data won't be corrupted.
i.e. the application must be written in a way to accept a request like that (however you want to do it).

C# Debugging: magical System Clock restore

The program I am working on is used to test operations in a time-based schedule. As such, one of the requirements is to change the system clock to provoke another application into firing events. This is simple enough. My program runs a script, which can set the clock. When the script starts, I store the DateTime.Now and create a Stopwatch. When the script ends, if it has modified the system clock I read the elapsed time, add it to my start time, and set the system clock that value. All fine so far. HOWEVER. If I debug my program and stop it before the script ends, that restore never happens. I was wondering if there was any way to get the C# debugger to forcibly call some piece of code (or perform some action such as reading the time from an NIST server) when it shuts down?
Stopping the debugger is the same as terminating the process, so there is no guarantee, what is happening.
Nevertheless consider to implement a dispose or a finalize method.
"I debug my program and stop it..."
So you're wondering why your program doesn't continue after you've stopped it?
You can debug your program and then simply detach the debugger when you're done - this will leave the program running.

C# NET Application not shutting down Java Process

I wrote a C# NET application (Console app that is run as a Service) that manages a Java process (Minecraft Game Server), and our Web Panel software manages my application. When the Java process stops, my application stops itself, and when my application stops, it stops the Java process.
The issue I am running into is that I deployed the software to all of our machines after extensive bug testing, but there seems to be a bug we missed where it is NOT shutting down the Java process sometimes. This bug is horrible as the Web Software tries to start my application, my application tries to start the Java process, but fails due to it being unable to IP bind (since the old process stayed open) and we wind up with 15-30 bugged Java processes running.
I am using CurrentDomain_UnhandledException to catch my application's crashes and call TerminateProcess().
I am using CtrlTypes.CTRL_C_EVENT and CtrlTypes.CTRL_CLOSE_EVENT to detect my application being closed which also calls the TerminateProcess() function.
I have tried both of the following methods...
static void TerminateProcess()
{
log.LogMessage("Minecraft Process Shutdown.");
SendProcessCmd("stop");
}
and
static void TerminateProcess()
{
log.LogMessage("Minecraft Process Shutdown.");
minecraftProcess.Kill();
}
However, I seem to be missing another way that my C# application is being shut down, because both ways seem to leave a Java process running every once in a while that I can't reproduce locally.
Well, you did not state any question, I’m going to guess you wanted to ask for other ways a process can get shut down, so that you can intercept it and ensure the Java process termination. Simply said: That is impossible (in full generality).
Just look at your own code: You are doing exactly the same thing to Minecraft: Calling TerminateProcess causes the target process to terminate immediately, without any chance to clean up. Should anyone call TerminateProcess on you (e.g. a user killing the process from Task Manager), your process just terminates immediately.
Also, some fatal exceptions are uncatchable, e.g. when your process dies on a stack overflow, you are not told, just terminated.
I guess you’d need to create another process, watching over your process… (Or rethink the whole architecture, creating and killing processes, especially with TerminateProcess, seems a bit rough to me.)

Ways to kill a running program and how to trap them?

We have different ways to kill a running C# program.
ctrl + C;
task bar then right click its icon, then select 'close' on the popup;
task manager, select the its executable name and then click end process;
console window, use kill command;
maybe more.
What I am asking here is how handle them in my C# program to guarantee my C# program exit gracefully when possible. I know how to trap ctrl + C, but don't the others. can you help me? thanks,
The best guarantee you have at code being run at exit is the finally statement.
Note though that your program will have to run in the try block when you use this mechanism.
I believe that the only time the block inside the finally is not executed are at:
A StackOverflowException;
Corrupted state exceptions (from .NET 4);
Forceful termination through the task manager (an unmanaged process kill);
Crash of the entire system (removing the power cable e.g.).
See Keep Your Code Running with the Reliability Features of the .NET Framework for an in depth analysis.
Scenario 2 basically calls Application.Exit(), which should amount to a graceful shutdown of all threads associated with your process. It also fires events you can use to perform any additional cleanup.
3 and 4 can be "trapped" by attaching a handler to the Application.ThreadException event of a WinForms app. This event is fired when any exception is about to be thrown out of the program to be handled by the runtime (which will terminate your assembly's execution and clean the sandbox). However, at this point there's very little you should do other than write something to the Event log or clean up any statics, like an IoC container or repository, and even that's problematic because if one of those objects caused the exception, you could very easily throw another exception in trying to deal with the last one.
Basically, if your user is using "kill" or "End Process" to close your app, there's something VERY wrong and you should probably address the underlying reason why a user would be doing that, before trying to gracefully capture such termination behaviors.
Cannot trap. You cannot avoid killing of a program. But you can always subscribe to kill. Just imaging how you can trap when people pull the power plug...
.NET 2.0
Subscribe to the AppDomain.CurrentDomain.ProcessExit event
.NET 3.5
Application.Exit Event
Useful links
AppDomain.CurrentDomain.ProcessExit and cleanup
How to detect when application terminates?
How to detect when main thread terminates?

Categories