为什么要杀死Excel进程是一件坏事?

我已经看到了很多关于如何确保Excel实际上退出的文章和问题,而且这个过程并没有维持下去。 以下是描述问题的知识库文章以及Microsoft推荐的解决scheme。 主要有:

'close files 'Quit Excel xlApp.quit() 'Release and collect garbage System.Runtime.InteropServices.Marshal.FinalReleaseComObject(xlApp) GC.Collect() GC.WaitForPendingFinalizers() 

许多人不build议杀死这个过程; 请参阅如何正确清理Excel互操作对象和了解.net中的垃圾收集

另一方面,很多人不推荐使用GC.Collect。 看看使用GC.Collect()有什么错误?

在我的经验中,杀死这个过程是确保Excel不见了的最快最容易的方法。 我的代码只杀死它启动的确切过程,没有其他的。 我确保closures所有打开的工作簿,退出应用程序并释放xlApp对象。 最后,我检查过程是否还活着,如果是的话就杀了它。

 <System.Runtime.InteropServices.DllImport("user32.dll", SetLastError:=True)> _ Private Shared Function GetWindowThreadProcessId(ByVal hWnd As IntPtr, _ ByRef lpdwProcessId As Integer) As Integer End Function Sub testKill() 'start the application Dim xlApp As Object = CreateObject("Excel.Application") 'do some work with Excel 'close any open files 'get the window handle Dim xlHWND As Integer = xlApp.hwnd 'this will have the process ID after call to GetWindowThreadProcessId Dim ProcIdXL As Integer = 0 'get the process ID GetWindowThreadProcessId(xlHWND, ProcIdXL) 'get the process Dim xproc As Process = Process.GetProcessById(ProcIdXL) 'Quit Excel xlApp.quit() 'Release System.Runtime.InteropServices.Marshal.FinalReleaseComObject(xlApp) 'set to nothing xlApp = Nothing 'kill the process if still running If Not xproc.HasExited Then xproc.Kill() End If End Sub 

我见过很多人说杀死这个过程是不好的,但是为什么我还没有看到任何定性的答案。 特别是在确定文件closures之后,Excel已经退出,我们只会杀死我们开始的确切过程。 我的问题是什么是杀死Excel进程的潜在问题。 这是否伤害perfomance? 会损害Excel吗?

许多人也会说,用好的编码,我不必杀死这个过程。 也许吧,但这并不能回答“为什么要杀死这个过程? closures文件后,退出Excel并释放对象; 为什么只是绝对确定这个过程已经过去,这是一件坏事呢?

编辑:也是什么实际上离开后退出Excel? 如果Excel可见,它似乎正常退出,从视图和任务栏中消失。 Excel实际上退出了,或者没有。 在我看来,Excel实际上已经退出了,我们只有一个空的进程shell运行。 任何人都可以评论呢?

编辑:我很有趣的注意到GC(又名垃圾收集)通过GC.Collect()GC.WaitForPendingFinalizers()将实际释放Excel退出后留下的进程shell。 这是否支持我的假设,即空的stream程shell真的是垃圾?

编辑:刚刚find了一个很好的网站上的问题: 杀死Excel的50种方法

看,事实是,你应该永远让应用程序正常退出,如果可能的话。 杀死应用程序是最后的手段。 我知道你确信在这种情况下你没有看到有什么问题,也许你是对的。 即使对系统没有任何负面影响,也不能改变这是错误的事实。 这就像违反法律,因为你知道你不会被抓住,反正这是一个无可救药的犯罪。

但是,您可能没有意识到的潜在副作用。 例如,当您强制终止一个应用程序,操作系统可能会保留它的崩溃数据。 或者它可能会向Microsoft发送事故遥测。 实质上,你告诉微软应用程序正在崩溃,导致他们的崩溃统计数据被略微扭曲。

另一个可能的副作用是registryconfiguration单元可能无法正确卸载。 您可能会不时在事件日志中看到此错误。 它通常发生在应用程序被强制closures并且没有正确closuresregistry的句柄时。

即使没有这些事情发生,你也不知道未来版本的操作系统可能会做什么。 今天什么工作,明天可能无法工作。 这就是为什么你应该总是遵循logging的API和指导方针,因为他们通常会非常努力地支持他们已经发表的内容,但通常不会很努力地支持他们明确告诉你不要做的事情。

当您使用自动化从另一个应用程序控制Office应用程序时,您偶尔必须像执行操作一样杀死Office进程,以避免“泄漏”不可见的Office应用程序。 这是Office应用程序试图既作为最终用户应用程序又作为自动化服务器的不幸结果。

当在服务器端使用Word时,我使用了或多或less相同的解决scheme(不要问为什么)。 无论我们付出多less努力来正确closuresWord,越来越多的“不可见”的Word进程将在服务器上累积。 唯一好的解决scheme是杀死那些在被指示退出后不会终止的进程。

当一个Windows进程被终止时,进程使用的所有资源都被操作系统清除,例如文件和registry句柄等其他操作系统句柄被closures,内存被释放等等。从操作系统的angular度来看,当过程终止。

但是,应用程序可能会创build正常关机期间要删除的临时文件。 随着时间的推移,这些孤立的文件可能会在磁盘上使用越来越多的空间。 另外,如果用户在应用程序中打开了其他文件,则在进程终止时可能会使这些文件处于不一致的状态,并且未保存的更改可能会丢失。 基本上,被杀的应用程序可以“泄漏”的是它打算在closures时清除或删除的文件。 “泄漏”的另一个来源是在networking上获取的资源(例如,在共享上打开的文件)。 但是,当进程终止时,networking句柄将最终变成“陈旧”并由networking服务器回收。

此外,我想指出,沃森博士将不会收集任何崩溃转储数据,如果一个进程被杀害。 这只发生在一个进程意外崩溃(例如有一个未处理的exception)。

底线:如果您仔细查杀Excel,可能是避免随时间stream逝“泄漏”无形Excel程序的最佳方法。 在系统重新启动之前让他们使用越来越多的系统资源的替代scheme是不可行的。 成本,如果有的话,应该只是临时文件夹中剩下的一些小文件。


作为自动化Office的替代scheme,您可以使用Open XML SDK来打开和修改Office文件。 最初它可能稍微复杂一些,但是完全避免了在这个过程中重复使用Office应用程序。

根据我的经验,程序在closures时会执行一些操作:

  1. 释放所有内存引用
  2. 删除任何临时或工作文件
  3. 保存任何状态数据

由于这些原因,使用app.Quit()以API描述的方式closuresExcel是至关重要的 。 在这个例子偏离了Norm的地方,就是API不会释放所有的COM对象。 这导致步骤1)不完整。 在任何情况下都无法确保应用程序有效closures,因为您可能无法始终控制创build哪些COM对象。

我发现使用Excel(其他办公软件)最好的方法是使用以下过程:

  1. 获取包含Excel名称的进程ID列表
  2. 打开Excel
  3. 重复步骤1.使用它来确定您创build的新Excel实例的进程ID
  4. 使用Excel
  5. 退出Excel,释放您创build的所有对象,并以Application.Quit()结束
  6. 杀死进程

这使Excel有机会释放任何对象,删除任何临时文件并在进程终止之前保存任何状态数据。 我通常创build一个负责pipe理Excel实例的单例类。 它实现了IDisposable,在处置时,它将退出所有剩余的Excel应用程序。