When I get a reference to a System.Diagnostics.Process, how can I know if a process is currently running?
15 Answers
This is a way to do it with the name:
Process[] pname = Process.GetProcessesByName("notepad"); if (pname.Length == 0) MessageBox.Show("nothing"); else MessageBox.Show("run"); You can loop all process to get the ID for later manipulation:
Process[] processlist = Process.GetProcesses(); foreach(Process theprocess in processlist){ Console.WriteLine("Process: {0} ID: {1}", theprocess.ProcessName, theprocess.Id); } 8 Comments
if/else statements that are only one line in length don't need to have curly braces to indicate the block statement. This also goes for foreach and for statements. It boils down to coding style.for info. Years of c# .net dev and I have never seen this style. Like they say, "you learn something new every day". Thank you for the post and the reply..This is the simplest way I found after using reflector. I created an extension method for that:
public static class ProcessExtensions { public static bool IsRunning(this Process process) { if (process == null) throw new ArgumentNullException("process"); try { Process.GetProcessById(process.Id); } catch (ArgumentException) { return false; } return true; } } The Process.GetProcessById(processId) method calls the ProcessManager.IsProcessRunning(processId) method and throws ArgumentException in case the process does not exist. For some reason the ProcessManager class is internal...
2 Comments
Synchronous solution :
void DisplayProcessStatus(Process process) { process.Refresh(); // Important if(process.HasExited) { Console.WriteLine("Exited."); } else { Console.WriteLine("Running."); } } Asynchronous solution:
void RegisterProcessExit(Process process) { // NOTE there will be a race condition with the caller here // how to fix it is left as an exercise process.Exited += process_Exited; } static void process_Exited(object sender, EventArgs e) { Console.WriteLine("Process has exited."); } reshefm had a pretty nice answer; however, it does not account for a situation in which the process was never started to begin with.
Here is a a modified version of what he posted.
public static bool IsRunning(this Process process) { try { Process.GetProcessById(process.Id).Dispose(); } catch (Exception e) when (e is ArgumentException or InvalidOperationException) { return false; } return true; } I removed his ArgumentNullException because its actually suppose to be a null reference exception and it gets thrown by the system anyway and I also accounted for the situation in which the process was never started to begin with or the close() method was used to close the process.
3 Comments
It depends on how reliable you want this function to be. If you want to know if the particular process instance you have is still running and available with 100% accuracy then you are out of luck. The reason being that from the managed process object there are only 2 ways to identify the process.
The first is the Process Id. Unfortunately, process ids are not unique and can be recycled. Searching the process list for a matching Id will only tell you that there is a process with the same id running, but it's not necessarily your process.
The second item is the Process Handle. It has the same problem though as the Id and it's more awkward to work with.
If you're looking for medium level reliability then checking the current process list for a process of the same ID is sufficient.
Comments
Process.GetProcesses() is the way to go. But you may need to use one or more different criteria to find your process, depending on how it is running (i.e. as a service or a normal app, whether or not it has a titlebar).
1 Comment
There are many problems associated with this, as other have seemed to partially address:
- Any instance members are not guaranteed to be thread safe. Meaning there are race conditions that may occur with the lifetime of the snapshot while trying to evaluate the properties of the object.
- The process handle will throw Win32Exception for ACCESS DENIED where permissions for evaluating this and other such properties aren't allowed.
- For ISN'T RUNNING status, an ArgumentException will also be raised when trying to evaluate some of its properties.
Whether the properties others have mentioned are internal or not, you can still obtain information from them via reflection if permission allows.
var x = obj.GetType().GetProperty("Name", BindingFlags.NonPublic | BindingFlags.Instance); You could pinvoke Win32 code for Snapshot or you can use WMI which is slower.
HANDLE CreateToolhelp32Snapshot( DWORD dwFlags, DWORD th32ProcessID ); Another option would be to OpenProcess / CloseProcess, but you will still run into the same issues with exceptions being thrown same as before.
For WMI - OnNewEvent.Properties["?"]:
- "ParentProcessID"
- "ProcessID"
- "ProcessName"
- "SECURITY_DESCRIPTOR"
- "SessionID"
- "Sid"
- "TIME_CREATED"
Comments
string process = "notepad"; if (Process.GetProcessesByName(process).Length > 0) { MessageBox.Show("Working"); } else { MessageBox.Show("Not Working"); } also you can use a timer for checking the process every time
5 Comments
length == 0 should display Not Working) but still gets the job done.Maybe (probably) I am reading the question wrongly, but are you looking for the HasExited property that will tell you that the process represented by your Process object has exited (either normally or not).
If the process you have a reference to has a UI you can use the Responding property to determine if the UI is currently responding to user input or not.
You can also set EnableRaisingEvents and handle the Exited event (which is sent asychronously) or call WaitForExit() if you want to block.
Comments
You can instantiate a Process instance once for the process you want and keep on tracking the process using that .NET Process object (it will keep on tracking till you call Close on that .NET object explicitly, even if the process it was tracking has died [this is to be able to give you time of process close, aka ExitTime etc.])
Quoting http://msdn.microsoft.com/en-us/library/fb4aw7b8.aspx:
When an associated process exits (that is, when it is shut down by the operation system through a normal or abnormal termination), the system stores administrative information about the process and returns to the component that had called WaitForExit. The Process component can then access the information, which includes the ExitTime, by using the Handle to the exited process.
Because the associated process has exited, the Handle property of the component no longer points to an existing process resource. Instead, the handle can be used only to access the operating system’s information about the process resource. The system is aware of handles to exited processes that have not been released by Process components, so it keeps the ExitTime and Handle information in memory until the Process component specifically frees the resources. For this reason, any time you call Start for a Process instance, call Close when the associated process has terminated and you no longer need any administrative information about it. Close frees the memory allocated to the exited process.
Comments
Despite of supported API from .Net frameworks regarding checking existing process by process ID, those functions are very slow. It costs a huge amount of CPU cycles to run Process.GetProcesses() or Process.GetProcessById/Name().
A much quicker method to check a running process by ID is to use native API OpenProcess(). If return handle is 0, the process doesn't exist. If handle is different than 0, the process is running. There's no guarantee this method would work 100% at all time due to permission.
2 Comments
Safe query a list of all active processes by name. If you are looking for all active processes that are not terminated or just traces of remout ones, then try this safe query without failures, in the style of try without exceptions... You will get the result in any case and without failures... If the method returned “true”, then the list will contain all the searched processes, otherwise - “false” and an empty list, and if the list is null, the name argument was not set correctly and there was no search...
/// <summary> /// Safe Try... /// </summary> /// <param name="processName"></param> /// <param name="processList"></param> /// <returns></returns> public static bool ProcessIsAnyRunning(this string processName, out List<Process> processList) { processList = null; var ret = !string.IsNullOrWhiteSpace(processName); if (ret) { var processArr = Process.GetProcessesByName(processName); ret = processArr.Length > 0; if (ret) { processList = new List<Process>(); foreach (var process in processArr) try { process.Refresh(); if (process.HasExited) process.Dispose(); else processList.Add(process); } catch { continue; } ret = processList.Count > 0; } } return ret; } 3 Comments
I tried Coincoin's solution :
Before processing some file, I copy it as a temporary file and open it.
When I'm done, I close the application if it is still open and delete the temporary file :
I just use a Process variable and check it afterwards :
private Process openApplication; private void btnOpenFile_Click(object sender, EventArgs e) { ... // copy current file to fileCache ... // open fileCache with proper application openApplication = System.Diagnostics.Process.Start( fileCache ); } Later I close the application :
... openApplication.Refresh(); // close application if it is still open if ( !openApplication.HasExited() ) { openApplication.Kill(); } // delete temporary file System.IO.File.Delete( fileCache ); It works ( so far )
1 Comment
openApplication.HasExited(), HasExited is not a function. The correct way would be openApplication.HasExited.Better way with mutex (kinda) implementation:
private static Mutex mutex; private static void Program() { bool isNewInstance; mutex = new Mutex(true, "Any COOL Program name", out isNewInstance); if (!isNewInstance) { MessageBox.Show("Another instance of the application is already running."); this.Close(); return; } }