控制台应用程序:关闭窗口与程序结束

时间:2014-07-30 16:29:44

标签: c# com console-application

我正在编写一个小型库来帮助管理Excel中的某些对象。我正在使用一个简单的控制台应用程序来测试这个DLL,该应用程序调用库,然后输出结果。然后,我可以以任何典型的方式结束程序,通常是通过点击返回(从而完成ReadLine调用)或点击窗口的关闭按钮。 但是,对Excel实例的引用会根据程序的退出方式而有所不同。

在我的程序中,如果找不到现有的Excel引用,我使用以下行:

_app = new ExcelInterop.Application();

其中_app是静态或单例类中Microsoft.Office.Interop.Excel.Application的实例(我已尝试过两者,两者都有相同的结果)。

假设程序创建了自己的实例(并且找不到已打开的实例):

  • 如果通过单击关闭窗口按钮退出程序,则实例将保持打开状态
  • 如果通过到达Main块中的代码末尾退出程序
  • ,则实例已释放,并且不再出现在任务管理器

有没有让所有程序结束的行为与后一种情况相同?此外,这个DLL将继续在WPF应用程序中使用,在WPF中是否有类似的问题?< / strong>或者大概,甚至?

也许最重要的是,这种行为的技术原因是什么?

1 个答案:

答案 0 :(得分:3)

对于公寓线程进程外COM服务器所需的COM互操作包装器对象,控制台模式程序是一个相当恶劣的地方。该计划证明了这个问题:

using System;

class Program {
    static void Main(string[] args) {
        var prg = new Program();
        Console.ReadLine();
    }
    ~Program() {
        Console.WriteLine("Clean-up completed");
        System.Threading.Thread.Sleep(1500);
    }
}

按两种方式尝试,按Enter键并单击“关闭”按钮。你会看到终结器永远不会被执行。当您单击“关闭”按钮时,操作系统会在有机会正常关闭之前终止该过程。

与COM包装器的终结器相同的问题。它们无法执行,因此IUnknown :: Release()不会被调用,Office程序完全不知道客户端程序不再存在。 Windows对于已放弃的进程外服务器有自己的清理工作,但由于其他一些神秘的原因,这对Office程序不起作用。

这解释了它,修复它并不容易。单击“关闭”按钮时,您必须运行register a callback。如果必要,将 app 引用设置为null(如果它仍在范围内)并强制终结器与GC.Collect()+ GC.WaitForPendingFinalizers()一起运行。请记住,这只是一个创可贴,而不是一个修复。当您忙于与Office程序通信时,用户中止您的程序时,它将无法工作。最好避免使用控制台模式项目。