Louis Rhys
Louis Rhys

Reputation: 35627

How to check if process is still running before calling Process.GetProcessById?

In .NET Process.GetProcessById throws an exception if the process with this ID is not running. How to safely call this method so that it won't throw an exception? I am thinking something like

if(Process.IsRunning(id)) return Process.GetProcessById(id);
else return null; //or do something else

But can't find any method to check the ID, other than probably getting all the running processes and check whether the id exist in the list.

Upvotes: 10

Views: 19817

Answers (4)

TarmoPikaro
TarmoPikaro

Reputation: 5233

Same code using pinvoke, this should be faster as GetProcesses, as it does not require all processes enumeration.

[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr OpenProcess(ProcessAccessFlags access, bool inheritHandle, int procId);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool CloseHandle(IntPtr hObject);

[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetExitCodeProcess(IntPtr hProcess, out uint lpExitCode);

[Flags]
public enum ProcessAccessFlags : uint
{
    All = 0x001F0FFF,
    Terminate = 0x00000001,
    CreateThread = 0x00000002,
    VirtualMemoryOperation = 0x00000008,
    VirtualMemoryRead = 0x00000010,
    VirtualMemoryWrite = 0x00000020,
    DuplicateHandle = 0x00000040,
    CreateProcess = 0x000000080,
    SetQuota = 0x00000100,
    SetInformation = 0x00000200,
    QueryInformation = 0x00000400,
    QueryLimitedInformation = 0x00001000,
    Synchronize = 0x00100000
}


/// <summary>
/// Checks if given process is still alive
/// </summary>
/// <param name="processId">process id</param>
/// <returns>true if process is alive, false if not</returns>
static public bool IsProcessAlive(int processId)
{
    IntPtr h = OpenProcess(ProcessAccessFlags.QueryInformation, true, processId);

    if (h == IntPtr.Zero)
        return false;

    uint code = 0;
    bool b = GetExitCodeProcess(h, out code);
    CloseHandle(h);

    if (b)
        b = (code == 259) /* STILL_ACTIVE  */;

    return b;
}

Upvotes: 3

Dmitrii Dovgopolyi
Dmitrii Dovgopolyi

Reputation: 6301

public Process GetProcByID(int id)
{
    Process[] processlist = Process.GetProcesses();
    return processlist.FirstOrDefault(pr => pr.Id == id);
}

I looked inside Process.GetProcessById method.

It uses internal static class ProcessManager to ensure, that process runs. ProcessManager gets all the processes currently running in system and checks there ids, so I think it is the best way to do it.

So you should consider the overhead of exception or the overhead of Process array.

Upvotes: 19

Mārtiņš Radiņš
Mārtiņš Radiņš

Reputation: 375

Yeah, using try + catch will probably do the trick. If the process is not running, nothing will happen instead of throwing an exception.

Upvotes: 1

Blablablaster
Blablablaster

Reputation: 3348

Just use try-catch block

Process p = null;
try{
  p = Process.GetProcessById(id);
}
catch(Exception){

}
return p;

Upvotes: 2

Related Questions