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(Int32processId, Int32 access, Boolean
throwIfExited)at System.Diagnostics.Process.GetProcessHandle(Int32access, 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.
The answer you quote may apply in your case. As I understand it, it’s basically saying that if the process you’re looking at is running under a different user account, then
HasExitedcan’t get the permissions it needs to determine if the process has exited.Now you say “the only Excel processes that exist would be created under my current user log-in.” But suppose that’s not the case. Suppose there’s another Excel process running on the same box, under another user account? (Maybe one got started by somebody else’s process using OLE Automation, and didn’t get cleaned up properly or has hung.) Then GetProcessesByName would pick it up, but HasExited would fail.
So before calling your OpenExcelProcessesCount() method, add a bit of logging to dump the process IDs of all the processes returned from GetProcessesByName(“Excel”). Then check these against Task Manager, or the number of Excel processes you expect to be running under your account. If there’s an ID there that doesn’t correspond to an “expected” Excel process, you could have a culprit.