我有以下代码部分,旨在计算当前打开的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%罚款.然后突然,今天,它一直给我一个例外,它读取以下内容:
Run Code Online (Sandbox Code Playgroud)Exception: ApplicationThreadException Message: Access is denied Stack Trace: at System.Diagnostics.ProcessManager.OpenProcess(Int32processId,Int32 access,Boolean throwIfExited)
Run Code Online (Sandbox Code Playgroud)at System.Diagnostics.Process.GetProcessHandle(Int32access,Boolean throwIfExited)
Run Code Online (Sandbox Code Playgroud)at System.Diagnostics.Process.get_HasExited() etc...
基本上,对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实例,这个实例非常腐败甚至"进程"操作也不一定稳定.没什么结论,但这是我现在能想到的全部.
对于那些花时间回答并帮助我的响应者,我感谢你.
如果目标进程正在升级并且您的进程没有运行,则Process.HasExited可以抛出访问被拒绝的异常.StartTime属性也是如此.
这是一篇关于此主题的博客文章,其中包含可能的解决方法:System.Diagnostics.Process类中的错误
您引用的答案可能适用于您的情况。据我了解,这基本上是说,如果您正在查看的进程在不同的用户帐户下运行,则HasExited无法获得确定进程是否已退出所需的权限。
现在您说“唯一存在的 Excel 进程将在我当前的用户登录下创建”。但假设情况并非如此。假设有另一个 Excel 进程在另一个用户帐户下在同一个机器上运行?(也许一个进程是由其他人使用 OLE 自动化的进程启动的,并且没有正确清理或已挂起。)然后 GetProcessesByName 会拾取它,但 HasExited 会失败。
因此,在调用 OpenExcelProcessesCount() 方法之前,添加一些日志记录以转储从 GetProcessesByName("Excel") 返回的所有进程的进程 ID。然后根据任务管理器或您希望在您的帐户下运行的 Excel 进程数检查这些内容。如果其中的 ID 与“预期”Excel 进程不对应,则可能是罪魁祸首。