Most ungraceful way to terminate a process (that's being terminated)? - c#

What is the most ungraceful way to really terminate a process?
I was trying to use Process.Kill (System.Diagnostics), but it has a drawback that renders it useless for me:
If the call to the Kill method is made while the process is currently terminating, a Win32Exception is thrown for Access Denied.
I'm in fact dealing with an application (which isn't mine) that crashes frequently and even gets stuck in the termination process in a manner that only rebooting would help.
Running TASKKILL /F /IM ... also exits with "Access denied". I also tried to P/Invoke TerminateProcess().
Although this question might be oddly specific, I'd be very thankful for an answer.

Shortly after asking this question I figured out why the application would hang in a fashion that only a reboot would help (many thanks to this answer!): Avast Anti-Virus. Once I removed that software from all workstations the 3rd party application still crashes, but it gets actually terminated after doing so and thus can be run again.
Thanks anyways!

See if this helps
private void Test(){
KillProcess("notepad");
}
private void KillProcess(string processName) {
Process[] appProcesses = Process.GetProcessesByName(processName);
if(appProcesses.Length == 0)
return;
// Kill and wait for app to exit
appProcesses[0].Kill();
appProcesses[0].WaitForExit();
}

Related

Kill process (windows 8) issues

I've installed Windows 8 around a month ago and have been having issues where when a process hangs I am unable to end/kill it. Neither task manager nor CMD Taskkill /f /PID #### will do the job, so I figured I'd write up my own process killer in C# and see what issues come up.
After writing up a small app I realized that I'm not all that smart as I thought - I'm still unable to end the process. At first I was able to find the process by name/PID:
Process p = Process.GetProcessById(aPid)
//or
foreach (Process p in Process.GetProcessesByName(aProcessName)
..and was getting "Access denied" exception when I tried to:
process.Kill();
..after a few attempts that changed and I would be unable to find the process anymore. Eg. when I tried to find it by name or PID nothing was returned, while the process still remained in the Task Manager and on my screen.
I have also read up on Process #MSDN and it says that "Access Denied" can be thrown if the process is already terminating or could not be terminated.. :(
Help? Is there really no way to FORCE end process?
Well, you are essentially running into the same problem that prevents Task Manager from terminating the process. There are two possible reasons. One is associated with the access denied exception, the process might have removed the access right to other processes to acquire a handle to the process. Since you are running on Windows 8 you have .NET 4.5 installed. Which provides a new method to the Process class, you can call EnterDebugMode(). That enables the SeDebugPrivilege, might be good enough to now make Kill() work.
The other is a much bigger problem, the process may have a thread active in kernel mode that is not exiting. Best way to diagnose that is by using Task Manager, Details tab, right-click one of the column headers and choose "Select Columns". Tick "Handles". Look at the displayed value for the process. If you see a non-zero value then the process is very likely to have a handle opened and is waiting for a device driver to perform an I/O request. And that device driver is otherwise impervious to Windows asking it to cancel the request. Narrowing down the troublemaker is not that easy, you have to know more about exactly what kind of I/O requests your process performs. Follow up on this by asking a question about it at superuser.com

How to stop process in C#, knowing its filename?

I have a programm that runs another one (lets call the first app Stater and the second app - Worker).
I use
process.start();
process.waiForExit();
process.Close();
in Starter.
But if Starter is forced to close while waiting for Worker (for some extern reason) Worker will be still in processes, blocking files, eating memory etc.
So, I want to check if Worker is already running before I will try to start it.
I've tried Process.GetProcessesByName("worker.exe") but no luck (even if I can see Worker in Task Manager).
I've seen some topics here about checking every process in memory for its modules, but still I already know the running file I hope to avoid such solution.
Any advices?
The reason you cannot find it is because you're using .exe. If the executable shows up as worker.exe in TaskManager, just call:
Process[] workers = Process.GetProcessesByName("worker")
foreach (Process worker in workers)
{
worker.Kill();
worker.WaitForExit();
worker.Dispose();
}
At the time of starting Worker process, save its ID in your application's configuration/setting file, in this way when you will launch your Starter process, it will first load that ID from settings file and will check if that process is currently running or not. If you want to immediately close Worker process, you can call process.Kill() on it.
This is much easier...
System.Diagnostics.Process.Start("cmd.exe","/c taskkill /IM notepad.exe");
This code will close the Notepad (if it is running). Type the program name you want to close with it's extension (.exe).
Some applications cannot be stopped without forcing.
Use /F after taskkill to force the action.
If you want to close the process tree use /T after program name.
System.Diagnostics.Process.Start("cmd.exe","/c taskkill /F /IM notepad.exe /T");
When you call GetProcessesByName("worker") you don't specify exe extension as explained in MSDN
And if you wish to keep a global variable with the process object that you have started you could simply use the process.Kill();
If you only need to detect that "worker" is running, a technically much superior solution is have it lock a global mutex for the duration of its lifetime. Any process that knows the mutex name (which is under your control) can then see if the mutex is locked (if it is, worker is running).
However this is not easy to implement correctly as there are many little details you want to get just right; even then, there might be a race condition of "starter" and "worker" are actually launched simultaneously etc (of course this problem, and many others, also apply to all other solutions so it cannot be considered a drawback).

C# is there anyway to instruct a code block to finish processing before the app gets shut down?

I know this won't work in all scenarios, but please keep in mind the following 3 scenarios:
An IIS reset - if the code is running inside IIS
A Server restart or shut down
User closes the app (if its a Windows form or Console App).
Lets say I have a code block that runs a loop. Is there a way to ensure at least that the current loop item gets processed before the app shuts down.
Like this...
Loop runs: 100 items, app gets shutdown (for reasons above), app is busy with item in loop 53 for example. It first finishes all code for that item between the foreach... and then allows the app to gracefully shutdown.
Is this type of thing possible?
Nothing I would do but If it is ok to abuse the system you might be able to use the CriticalFinalizerObject
It is guaranteed to execute
even in situations where the CLR forcibly unloads an application domain or aborts a thread
I really don't think so. You are stuck in front of windows. Windows take that kind of decisions for you.. IF somebody is shutting down the pc, then you are just shut down. This is the same scenario as if they where a power failure. What will you do in that case?
For a normal application: While your code is running in a foreground thread (not ThreadPool or Thread.IsBackground == true) it will not be aborted mid-execution, unless the user forcibly quits the process.
If you are running your loop in a background thread, you can try handling the exit event of the application, waiting for the loop to finish or at least reach a stable state before being aborted.
In most apps you can handle close event and not allow it but you can't do anything when user decides to kill your process. So i would say that its not possible.
How about doing this. using a try catch and finally in the static void Main
Here even if you end task the application, finally will run. not sure about power failure.
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
try
{
Application.Run(new Form1());
}
finally
{
MessageBox.Show("I run always.");
}
}
Hope it helps

C# Crash not caught by Debugger

I have a pretty large project that just recently started crashing on exit. I am not the greatest C# coder but everything generally works as intended. In this case however, when I close my console application, it crashes but is not caught by the MSVC Debugger.
1) When I build it in Release and run it, it generally always crashes when I exit.
2) When I build it in Debug and run it, it seems to only crash on exit every 1 out of 3-5 times.
I did manage to get the error though when it didn't exit properly, but unfortunately the Exit Code doesn't match anything I can find online.
The program '[11108] MCDaemon.vshost.exe: Managed (v4.0.30319)' has exited with code -1073741510 (0xc000013a).
From what I have read on other people's questions, this is generally caused by Unmanaged Code acting up. Is there any way I can actually find out what the issue is short of a massive amounts of debug lines?
EDIT
From an answer below, this is the code causing the Exit code, but I don't really see anything issue with it.
public static Boolean Handler(MyWin32.CtrlTypes CtrlType)
{
// A switch to handle the event type.
switch (CtrlType)
{
case MyWin32.CtrlTypes.CTRL_C_EVENT:
Program.TerminateProcess();
break;
case MyWin32.CtrlTypes.CTRL_CLOSE_EVENT:
Program.TerminateProcess();
break;
}
return true;
}
public static void TerminateProcess()
{
// Stop the Poll Timer from Running
PollTimer.Stop();
log.LogMessage("Process is being Shutdown.");
log.LogMessage("Requesting Process to Stop....");
SendProcessCmd("stop");
// Wait and make sure it has exited
Thread.Sleep(5000);
if (!myProcess.HasExited)
{
log.LogMessage("My Process did not stop on its own, forcing Process to quit.");
myProcess.Kill();
}
log.LogMessage("My Process has been Shutdown.");
}
// Wait and make sure it has exited
Thread.Sleep(5000);
That's the problem statement. You are pinvoking SetConsoleCtrlHandler() in your code to get your Handler method called. Windows requires the control handler to be responsive and not take too long to return from the callback. The timeout for the CTRL_CLOSE_EVENT is exactly 5 seconds, explaining why it sometimes works. If it takes longer then Windows pulls the plug on the process.
You'll need to implement TerminateProcess differently. Killing a process is fairly arbitrary, you ought to be better off just not doing this. Or start another guard process. I can't make that call though.
0xC000013A: The application terminated as a result of a Ctrl+C.
This is because you closed the console window, and the application wasn't expecting you to, so Windows terminated it for you.
Sorry, but I don't know how to catch a console window close event in managed code.

Alternative methods to kill a running process in C#

I am having a bit of trouble trying to terminate a process, I realize there is a fair amount of recourses on this site alone, but I was wondering if there's any alternative ways of terminating an application rather than something typical such as:
Process[] procs = Process.GetProcessesByName("test");
foreach (Process proc in procs)
proc.Kill();
There's Process.CloseMainWindow, which nicely asks the process to quit (as opposed to Process.Kill, which shoots down the process and can have negative side effects).
There are only 2 ways in C# to close the Process (AFAIK) using Process.Kill() and Process.CloseMainWindow(), Kill sends an immediate KILL signal to the application and forces it to close immediately. CloseMainWindow uses SendWindowMessage to send a CLOSE signal to the main application. Kill can be unsafe because it immediately stops the process. CloseMainWindow can be followed by Process.WaitForExit so that you can be sure that the application has closed and may continue to do work knowing that the process you told to exit has exited correctly. As posted by Heinzi's comment please be a little more specific I'm just trying to expand on what was said in the hopes that this is what you require.
Very simple, just need to get the process name and kill it, don't try to do anything fancy, sometimes less is more...
Process[] prs = Process.GetProcesses();
foreach (Process pr in prs)
{
if (pr.ProcessName == "test")
{
pr.Kill();
}
}
This idea is not good. There could be another running process(es) with that name. Do you want any process with that name to be terminated? Unless you are writing a Task Manager/Process Explorer kind of application, you should never do that. And even with TM kind of application, you close the process by grabbing its handle/Process object, and not by name.
Thy can't you ask the target process to close itself gracefully? May be you can use a named mutex, the target thread would wait on that mutex. When you signal that named-mutex from another process, the target thread would know it is time to exit and eventually exit.

Categories

Resources