excel进程在外部closures时处理错误
我正在写一个与Excel交互的程序。 当通过任务pipe理器杀死excel时,我关于closures应用程序有点问题。
当我的程序启动时,它将设置Excel.Application ObjApp = new Excel.Application();
当它closures时,它以此结束
if (ObjApp != null) { ObjApp = null; } GC.Collect(); GC.WaitForPendingFinalizers(); ObjApp.Quit(); Environment.Exit(0);
但是,如果excel通过任务pipe理器被杀害,我退出,我得到这个
ObjApp.Quit();
“NullReferenceExceptionObjApp.Quit();
用户代码处理”ObjApp.Quit();
基本上我需要弄清楚的是如何说
“如果ObjApp(我的Excel实例)仍然可用,请退出,否则不要。 我该如何解决这个问题?
你不应该担心你无法控制的事情。 无论用户决定终止您的程序使用或不使用的Excel应用程序,都不是您应该试图弄清楚的事情(没有安全的方法来确定是否是这种情况,您总是可以结束竞争状态,但是我们不要弄错了)。
那你应该怎么做? 实施代码来处理应用程序可以处理的任何合理的故障情况。 什么是失败的原因是不相关的,它可以是任何东西:它可能是closures应用程序的用户,但它也可能是一些晦涩的Excel错误崩溃的应用程序, 操作系统打嗝,硬件故障,你有什么。
你怎么做? 那么,使用exception处理 :
try { //Normal code path goes here. Assume appObj is running; ObjApp.Quit(); } //optional catch clauses here finally { //Safe clean up you want running in normal execution or any managable //scenario. By safe I mean you shouldn't be handling/saving/modifying //any sensitive data, you should just clean up your COM objects. //Anything potentially unsafe should be handled in specific catch //clauses where you know the nature of the exception and you can take //specific measures to recover or shut down safely. //In some unrecoverable scenarios this might not even run. Marshal.FinalReleaseComObject(ObjApp); }
您可以为特定的exceptiontypes添加catch
子句以用于login目的,或者通知用户发生了意外事件; COMException
是一个不错的select,任何其他exception都应该被传递到调用堆栈,并让其他知道更好处理的exception处理。
第一
GC.WaitForPendingFinalizers()
将运行objects
析构函数。
对于你的例子,当ObjApp == null
GC可能会破坏对象ObjApp
。 然后ObjApp
将由null。
ObjApp.Quit()
必须通过调用befeore GC.WaitForPendingFinalizers()
其次您将ObjApp
设置为null
值,然后调用ObjApp.Quit()
。 如果Quit()
方法是非静态的,那么程序抛出NullReferenceException
并且是预期的。
尝试这个:
ObjApp.Quit(); if (ObjApp != null) { ObjApp = null; } GC.Collect(); GC.WaitForPendingFinalizers(); Environment.Exit(0);
个人意见,当我closuresExcel文件我这样做:
...// this.workbook.Close(); this.application.Workbooks.Close(); this.application.Quit(); } finally { Marshal.FinalReleaseComObject(this.autoFitRange); GC.Collect(); Marshal.ReleaseComObject(this.numberFormatRange); GC.Collect(); Marshal.ReleaseComObject(this.range); GC.Collect(); Marshal.ReleaseComObject(this.workbook); GC.Collect(); Marshal.ReleaseComObject(this.sheet); GC.Collect(); Marshal.ReleaseComObject(this.workbooks); GC.Collect(); Marshal.ReleaseComObject(this.application); GC.Collect();
正如你所看到的,我使用ReleaseComObject来运行使用COM
excel库里创build的所有对象。 如果我这样做,我成功地closures了Excel,这个过程将从任务pipe理器中消失。
愿这帮助你。