【问题标题】:How do I catch FileNotFoundException when running on Mono and a DLL is missing?在 Mono 上运行并且缺少 DLL 时如何捕获 FileNotFoundException?
【发布时间】:2010-08-18 18:41:54
【问题描述】:

我有一个带有 vs2010 的 windows 7 x64 桌面和一个带有 mono 和 monodevelop 的 linux 虚拟盒安装。我用 vs2010 编译了以下程序并在 linux 虚拟机中运行它并失败并出现看似无法捕获的 FileNotFoundException。如果我在虚拟机中编译并在windows中运行,效果很好。

问题似乎是在无法加载 dll 时,Mono 在 Main() 之前抛出了无法捕获的异常。有没有办法重组我的程序或强制单声道,以便我可以捕捉到这个异常?

我正在尝试根据运行时可用的内容编写一个在 WPF 或 GTK 中具有接口的单个​​程序。

using System;  
#if __MonoCS__  
using Gtk;  
#else  
using System.Windows;  
#endif  
using System.IO;  
using System.Runtime.CompilerServices;  
using System.Collections.Generic;  

namespace Test {

 public static class Program {

  [STAThread]
  public static void Main() {
   try {
    Main2();
   } catch (FileNotFoundException e) {
    Console.WriteLine("Caught FileNotFoundException");
    Console.WriteLine("FileName = {0}", e.FileName);
   }
  }

  [MethodImpl(MethodImplOptions.NoInlining)]
  public static void Main2() {
#if __MonoCS__  
   Application.Init();  
#else  
   Window w = new Window();  
#endif  
  }

 }

}

【问题讨论】:

    标签: c# .net dll mono filenotfoundexception


    【解决方案1】:

    您将自己暴露于 JIT 编译器的实现细节。它为缺少的程序集抛出异常的确切时间取决于它将 IL 转换为机器代码的热切程度。我知道 Microsoft jitter 确实是即时的,它一次编译一个方法,就在它即将执行之前。尽管这受是否附加调试器的影响。比如说,如果 Mono 编译整个类,那你就死定了。抖动会在 Main() 启动之前抛出。

    如果将 Main2() 放在另一个类中,它可能会更好。最好的办法是提供一个可用的组件,如有必要,可以使用一个虚拟组件。

    【讨论】:

    • 将 Main2 放在另一个类中没有帮助。你说的很有道理,尽管抛出一个无法捕获的异常的想法让我非常沮丧。我将把这个问题留得更久,看看是否有人有一个神奇的答案,但我似乎不可避免地会给你答案。谢谢。
    【解决方案2】:

    什么 DLL 没有找到?我假设,从你的代码来看,它可能是 WinForms。我对 C# 预处理器并不完全熟悉,但我认为 #if __MonoCS__ 作为预处理器定义可能更有用(或可能只起作用),也就是说,它在运行时不会改变。您可以尝试在项目设置中为 Mono 构建定义 __MonoCS__ 并运行它(我认为 VS 在默认情况下没有定义它,所以它可能无论如何都在尝试使用 WinForms)。

    要尝试的另一件事是注释掉 using System.Windows 及其所有相关代码(仅使用 GTK/Mono 路径)并测试它是否在 Windows 上构建并在两者上运行。如果是这样,那么您已将可能的问题缩小到仅包括在内,并且应该更容易从那里解决。

    【讨论】:

    • 在 Linux PresentationFramework 上是第一个触发异常的 DLL。在 Windows 上是 GTK-Sharp。本程序不使用 Winforms。该程序的重​​点是让它抛出一个异常,这样我就可以看到在哪里捕获它是合适的,所以注释掉你提到的各种代码会使这个练习变得不可能。如果有更好的方法使单个 .exe 能够在运行时在 2 个 API 之间进行选择,我会全力以赴。
    • 啊,所以您使用的是演示框架,而不是表单?我认为变化不大。要使单个 EXE 能够在其中任何一个上运行,最好的方法是使用跨平台 UI。 GTK# 也适用于 Windows,所以如果它不麻烦,使用它应该对你有用。我最初说的是你得到异常的原因是系统没有像你期望的那样关注#ifs,所以改变这些可能更有帮助。不过,我不熟悉 C# 预处理器。如果没有其他方法,您可能只需要构建两次,一次用于 Windows,一次用于 Linux。
    • 它完全按照我的预期关注#ifs。他们应该强制它总是使用错误的库。我想要例外。该程序的重​​点是生成异常以捕获它。我想在许多情况下使用这种技术从各种库中进行选择。 GTK 和 WPF 只是一个例子。似乎不可能做我想做的事。我不想强迫 Windows 用户使用 gtk。
    【解决方案3】:

    我建议您在不同的程序集中实现特定于平台的 GUI,而不是依赖于引用程序集加载的惰性,也许实现一个通用接口。主程序集将没有对特定 GUI 工具包的直接引用,但会使用反射尝试从 GAC 加载 WPF 或 GTK,并基于此使用反射加载特定 GUI dll 程序集并实例化和使用 GUI 实现.

    类似:

    • ProgramName.exe - 包含Main 入口点、IPlatformGui 和所有平台共享的逻辑
    • ProgramName.Gtk.dll - 包含GtkGui : IPlatformGui
    • ProgramName.Wpf.dll - 包含WpfGui : IPlatformGui

    【讨论】:

    • 我可能会求助于你所说的。 TBH 我不认为我有任何其他选择。我假设我不能在这里选择多个答案?我想感谢你们俩。
    猜你喜欢
    • 1970-01-01
    • 2018-01-17
    • 1970-01-01
    • 2011-03-23
    • 1970-01-01
    • 2013-06-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多