当带到前台时,应用程序崩溃并显示“...停止工作”

Application crashes with "... stopped working" when brought to foreground

我最近收到了修复一个工具中的错误的请求,该工具是由一位已离开公司的同事创建的。

这个工具基本上是一个基于 .NET-Framework 4 的 WinForms 应用程序。它通常可以正常工作,但以下情况会导致随机崩溃:

如果程序在后台(没有焦点)并在一段时间后被用户带到前台(焦点/激活),它会崩溃并显示消息 "ToolName has stopped working".

如果在调试器下执行,

ToolName 将替换为 "vshost.exe"。 没有显示其他错误消息。不知道是哪一行代码出错了

一些附加信息:

"The current debugger is configured to debug code that uses Microsoft .NET Framework v 1.0, 1.1, or 2.0. An unhandled exception is being thrown from .NET Framework v4.0 code."

我试图通过添加全局异常处理程序来获取有关崩溃的更多信息,这些处理程序应该使用堆栈跟踪创建一个 MessageBox,但它们不会触发:

[STAThread]
static void Main()
{
  AppDomain currentDomain = default(AppDomain);
  currentDomain = AppDomain.CurrentDomain;

  currentDomain.UnhandledException += GlobalUnhandledExceptionHandler;
  System.Windows.Forms.Application.ThreadException += GlobalThreadExceptionHandler;

  // ...
}

private static void GlobalUnhandledExceptionHandler(object sender, UnhandledExceptionEventArgs e)
{
  Exception ex = default(Exception);
  ex = (Exception)e.ExceptionObject;

  MessageBox.Show(ex.Message + "\n" + ex.StackTrace);
}

private static void GlobalThreadExceptionHandler(object sender, System.Threading.ThreadExceptionEventArgs e)
{
  Exception ex = default(Exception);
  ex = e.Exception;

  MessageBox.Show(ex.Message + "\n" + ex.StackTrace);
}

无奈之下,我在 Application.Run 周围添加了一个 try-catch-Block,它也不会触发:

try
{
   Application.Run(new MainForm());
}
catch (Exception e)
{
   MessageBox.Show(e.Message);
}

当我 运行 遇到这样的问题时,我通常从事件查看器开始。 Windows 会将应用程序崩溃记录到事件查看器,即使它们是无声的。有时,它能够吐出一个堆栈跟踪,这可以使事情变得更容易。根据我的经验,应用程序正在无声地崩溃,因为它正在尝试加载一些缺少的依赖项并且它正在获取 TypeInitializationException。

如果没有关于应用程序的更多信息,我很难告诉你根本原因是什么。应用程序是否加载任何第 3 方库?应用程序中发生了任何自定义控制图吗?我相信 .NET 延迟加载类型。如果在应用程序尝试绘制自身之前不需要某个类型,那么在应用程序首次显示之前可能不会加载它。那时,如果缺少类型,应用程序将崩溃。应用程序启动时最小化了吗?崩溃是随机的还是一致的?意思是,如果您在启动时显示应用程序,它是否有效?还是当您第一次显示应用程序时它总是崩溃?

您使用的 Visual Studio 是什么版本?您的项目文件是否设置为 .NET 4?您可以 select 附加到进程时附加什么代码类型。在 Attach to Process 对话框中,按 Attach to 右侧的 "Select"(默认应为 Automatic:Native code)。然后 select 所需的代码类型。此选项在 VS 2010 和 2013 中位于同一位置。

我摆脱了崩溃:

应用程序创建了一个以本机语言实现的第 3 方 COM 对象的实例。此实例是在线程中创建的(可能是为了避免 Loader Lock-如果在主线程上创建会出现的错误)。

在事件日志(在控制面板中找到)中有关于崩溃的更多信息。有导致崩溃的 DLL 名称的提示(感谢 Tom 的提示!)。

我将 COM 对象的创建从早期绑定(通过动态和 Activator.CreateInstance())更改为后期绑定(我在 Visual Studio 中添加了对 COM 对象的引用) .这允许我在启动期间在主线程上创建 COM 对象的实例。

从那时起我就没有遇到过任何崩溃。