Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

If 'Process.HasExited' throws an exception, can I assume that the process is gone?

Tags:

c#

process

I have the following code section, designed to count how many Excel processes are currently open:

Func<int> OpenExcelProcessesCount = 
    () => System.Diagnostics.Process.GetProcessesByName("Excel")
              .Where(p => !p.HasExited)
              .Count();

And then later I retrieve the count at various points, with code such as the following:

int excelAppCount = OpenExcelProcessesCount();

This code has been running 100% fine for months. Then suddenly, today, it is consistently giving me an exception that reads the following:

Exception: ApplicationThreadException

Message: Access is denied

Stack Trace:

   at System.Diagnostics.ProcessManager.OpenProcess(Int32

processId, Int32 access, Boolean throwIfExited)

   at System.Diagnostics.Process.GetProcessHandle(Int32

access, Boolean throwIfExited)

   at System.Diagnostics.Process.get_HasExited()

   etc...

Basically, the call to Process.HasExited (which shows up as System.Diagnostics.Process.get_HasExited() in the stack trace, above) is failing. The error message "Access is denied" sounds like I don't have administrative privileges for the process, but the only Excel processes that exist would be created under my current user log-in, and the user can always access their own processes. My .NET code is also running under full trust.

The line that is ultimately failing is System.Diagnostics.ProcessManager.OpenProcess(Int32 processId, Int32 access, Boolean throwIfExited). I wonder if it is being passed in a value of 'true' for the 'throwIfExited' parameter. If this is the case, then I suppose that I could protect the call to Process.HasExited with a try-catch block and assume that if this fails that HasExited is, in fact, 'true'. But is this a safe assumption??

I am uneasy making a presumption like this, especially since the error message is "Access is denied." Does anyone have any ideas on how I might address this, or what I might test in an attempt to figure out what is going on?

The only similar thread I could find on Stack Overflow was the following: Why did hasExited throw ‘System.ComponentModel.Win32Exception’?. The answer given there was:

"Since you are doing runas, you only get SYNCHRONIZE access on the handle, not PROCESS_QUERY_INFORMATION access, hence GetExitCodeProcess fails, which results in hasEnded throwing a Win32 exception."

I don't really understand this answer and do not know if this applies in my case, but I thought I should mention it. If anyone feels that it is likely that this is the situation that I am facing, then if someone could try to clarify this answer for me, I would greatly appreciate it. (I'm an Excel programmer, I do not have much experience working with processes.)

Much thanks in advance...

Update:

Best I can tell, this is was a one-off corruption of some sort. The issues I faced started becoming increasingly bizarre as what had been a perfectly functioning set of unit tests was starting to have breakdowns at other "impossible" locations. A simple reboot corrected this issue and everything else I was facing.

My best guess is that I had some sort of bizarre corruption. Perhaps the ROT was corupted, and/or I had a hanging instance of Excel that was so corrupt that even 'Process' operations were not necessarily stable. Nothing conclusive, but this is all I can figure for now.

To the responders who took the time answer and help me out, I thank you.

like image 501
Mike Rosenblum Avatar asked Dec 26 '09 01:12

Mike Rosenblum


1 Answers

Process.HasExited can throw an access denied exception if the target process is running elevated and your process isn't. The same happens with StartTime property, too.

I have written a blog post about this topic with a possible workaround: Bugs in System.Diagnostics.Process Class

The stack trace in the question also looks similar to the one that I have in the blog.

like image 163
Giorgi Avatar answered Sep 21 '22 20:09

Giorgi