9

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.

Louis Rhys
  • 34,517
  • 56
  • 153
  • 221

4 Answers4

17
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.

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
Dmitrii Dovgopolyi
  • 6,231
  • 2
  • 27
  • 44
3

Just use try-catch block

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

}
return p;
Blablablaster
  • 3,238
  • 3
  • 31
  • 33
1

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

1

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;
}
TarmoPikaro
  • 4,723
  • 2
  • 50
  • 62