如果'Process.HasExited'抛出异常,我可以假设该过程消失了吗?

Mik*_*lum 5 c# process

我有以下代码部分,旨在计算当前打开的Excel进程数:

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

然后我在各个点检索计数,代码如下:

int excelAppCount = OpenExcelProcessesCount();
Run Code Online (Sandbox Code Playgroud)

这段代码已经运行了几个月100%罚款.然后突然,今天,它一直给我一个例外,它读取以下内容:

Exception: ApplicationThreadException

Message: Access is denied

Stack Trace:

   at System.Diagnostics.ProcessManager.OpenProcess(Int32
Run Code Online (Sandbox Code Playgroud)

processId,Int32 access,Boolean throwIfExited)

   at System.Diagnostics.Process.GetProcessHandle(Int32
Run Code Online (Sandbox Code Playgroud)

access,Boolean throwIfExited)

   at System.Diagnostics.Process.get_HasExited()

   etc...
Run Code Online (Sandbox Code Playgroud)

基本上,对Process.HasExited(System.Diagnostics.Process.get_HasExited()在上面的堆栈跟踪中显示)的调用失败.错误消息"访问被拒绝"听起来像我没有该进程的管理权限,但是在我当前的用户登录下将创建唯一存在的Excel进程,并且用户始终可以访问自己的进程.我的.NET代码也在完全信任下运行.

最终失败的路线是System.Diagnostics.ProcessManager.OpenProcess(Int32 processId, Int32 access, Boolean throwIfExited).我想知道它是否以'throwIfExited'参数的'true'值传递.如果是这种情况,那么我想我可以Process.HasExited使用try-catch块保护调用,并假设如果失败,HasExited实际上是'true'.但这是一个安全的假设吗?

我不安地做出这样的假设,特别是因为错误信息是"访问被拒绝".有没有人对我如何解决这个问题有任何想法,或者我可能会试图弄清楚发生了什么?

我在Stack Overflow上找到的唯一类似的线程如下:为什么hasExited抛出'System.ComponentModel.Win32Exception'?.那里给出的答案是:

"由于你正在运行runas,你只能在句柄上获得SYNCHRONIZE访问,而不是PROCESS_QUERY_INFORMATION访问,因此GetExitCodeProcess失败,这导致hasEnded抛出Win32异常."

我真的不明白这个答案,不知道这是否适用于我的情况,但我想我应该提一下.如果有人觉得这可能是我所面临的情况,那么如果有人可以尝试为我澄清这个答案,我将非常感激.(我是一名Excel程序员,我没有太多使用流程的经验.)

非常感谢...

更新:

我能说的最好,这是一种一次性的腐败.我所面临的问题开始变得越来越奇怪,因为一组功能完善的单元测试开始在其他"不可能"的位置出现故障.一个简单的重新启动纠正了这个问题和我面临的一切.

我最好的猜测是,我有一些奇怪的腐败.也许ROT已经被破坏了,和/或我有一个挂起的Excel实例,这个实例非常腐败甚至"进程"操作也不一定稳定.没什么结论,但这是我现在能想到的全部.

对于那些花时间回答并帮助我的响应者,我感谢你.

Gio*_*rgi 6

如果目标进程正在升级并且您的进程没有运行,则Process.HasExited可以抛出访问被拒绝的异常.StartTime属性也是如此.

这是一篇关于此主题的博客文章,其中包含可能的解决方法:System.Diagnostics.Process类中的错误


ito*_*son 4

您引用的答案可能适用于您的情况。据我了解,这基本上是说,如果您正在查看的进程在不同的用户帐户下运行,则HasExited无法获得确定进程是否已退出所需的权限。

现在您说“唯一存在的 Excel 进程将在我当前的用户登录下创建”。但假设情况并非如此。假设有另一个 Excel 进程在另一个用户帐户下在同一个机器上运行?(也许一个进程是由其他人使用 OLE 自动化的进程启动的,并且没有正确清理或已挂起。)然后 GetProcessesByName 会拾取它,但 HasExited 会失败。

因此,在调用 OpenExcelProcessesCount() 方法之前,添加一些日志记录以转储从 GetProcessesByName("Excel") 返回的所有进程的进程 ID。然后根据任务管理器或您希望在您的帐户下运行的 Excel 进程数检查这些内容。如果其中的 ID 与“预期”Excel 进程不对应,则可能是罪魁祸首。