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(); “NullReferenceException ObjApp.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理器中消失。

愿这帮助你。