Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/260.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 控制台应用程序:关闭窗口与程序结束_C#_Com_Console Application - Fatal编程技术网

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

C# 控制台应用程序:关闭窗口与程序结束,c#,com,console-application,C#,Com,Console Application,我正在编写一个小库来帮助管理Excel中的一些对象。我正在使用一个简单的控制台应用程序测试这个DLL,该应用程序调用库,然后打印结果。然后,我可以用任何一种典型的方式结束程序,通常是点击return(从而完成ReadLine调用)或点击窗口的close按钮但是,对Excel实例的引用会根据程序的退出方式表现出不同的行为。 在我的程序中,如果找不到对Excel的现有引用,我将使用以下行: _app = new ExcelInterop.Application(); 其中,\u app是静态类或单

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

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

_app = new ExcelInterop.Application();
其中,
\u app
是静态类或单例类中的
Microsoft.Office.Interop.Excel.Application
的一个实例(我已经尝试了这两种方法,两种方法都有相同的结果)

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

  • 如果通过单击关闭窗口按钮退出程序,实例将保持打开状态:
  • 如果程序通过到达
    Main
    块中的代码末尾而退出,则实例将被释放,并且不再显示在任务管理器中
是否有办法使所有程序端都像后一种情况那样运行?此外,此DLL将继续在WPF应用程序中使用,WPF中是否存在类似的问题?或者总体上是否存在类似的问题


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

控制台模式程序对于从process 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键和单击Close按钮,尝试两种方法。您将看到终结器从未执行过。单击“关闭”按钮时,操作系统会在进程有机会正常关闭之前终止进程

COM包装器的终结器也存在同样的问题。它们无法执行,因此不会调用IUnknown::Release(),并且Office程序完全不知道客户端程序已不存在。Windows对废弃的进程外服务器有自己的清理功能,但由于某些神秘的原因,这对Office程序不起作用


这就解释了,修复它并不是那么容易。当单击“关闭”按钮时,必须运行该命令。如有必要,如果应用程序引用仍在作用域中,请将其设置为null,并强制终结器与GC.Collect()+GC.WaitForPendingFinalizers()一起运行。请记住,这只是一个创可贴,而不是修复。当用户在您忙于与Office程序对话时中止您的程序时,它将不起作用。避免控制台模式的项目是最好的。

也许你可以整理一下像@jgok222这样的接近事件,这似乎是一个很好的结论,但是你知道在幕后到底发生了什么吗?最让人困惑的是,目前我还没有编写任何清理代码。我完全希望该实例在所有情况下都保持打开状态。我想我在推我不完全理解的代码时感到有点不安。回答得很好!正是我想要的。关闭按钮盒是否是控制台应用程序独有的?这是我在WPF中必须担心的事情吗?该应用程序将成为WPF关闭事件的一部分,它充分利用了WPF的关闭事件。GUI应用程序没有这个问题。太棒了,在这种情况下,我想我会创建一个公共清理方法,让任何控制台开发人员(我怀疑他们中的任何人)为自己的程序处理事件侦听器。@SandyGifford是“public cleanup method”正在实现
IDisposeable
接口,并将清理代码放入其中。然后,您的类的用户可以使用
语句将包装器的实例放入他们自己的
中,或者将他们的类
IDisposeable
也放入其中并将其处理掉。