我正在编写一个与excel交互的程序。关于在通过任务管理器杀死excel时关闭我的应用程序,我遇到了一些问题。
当我的程序启动时,它会设置Excel.Application ObjApp = new Excel.Application();
关闭时,以
结束if (ObjApp != null)
{
ObjApp = null;
}
GC.Collect();
GC.WaitForPendingFinalizers();
ObjApp.Quit();
Environment.Exit(0);
但是,如果通过任务管理器杀死excel并退出,我会得到这个
" NullReferenceException未被用户代码"处理在
ObjApp.Quit();
基本上我需要弄清楚的是怎么说
"如果ObjApp(我的Excel实例)仍然可用,请退出,否则不要。" 我该如何解决这个问题?
答案 0 :(得分:2)
你不应该担心你无法控制的事情。用户决定终止程序正在使用的 Excel 应用程序是不是你应该试图找出的东西(没有安全的方法来确定是否是这种情况,你可以总是以竞争条件结束,但不要让我们陷入困境。)
那你该怎么办?实现代码,处理应用程序可以处理的任何合理的故障情况。失败的原因究竟是什么并不重要,它可以是任何东西:它可能是用户关闭应用程序,但它也可能是一些模糊的 Excel 错误导致应用程序崩溃, OS 打嗝,硬件故障,你有什么。
你是怎么做到的?好吧,使用exception handling:
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);
}
您可以为特定的异常类型添加catch
子句以用于登录,或者通知用户发生了意外情况;我认为COMException
是一个很好的选择,任何其他异常都应该传递给调用堆栈,并让其他知道更好的人处理它。
答案 1 :(得分:0)
首先
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);
当我关闭Excel文件时,我这样做:
...//
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
excel libary期间为我创建的所有对象运行COM
。如果我这样做,我就会成功关闭Excel,并且该过程将从任务管理器中消失。
这可以帮助你。