2010-08-18 91 views
0

我有一个Windows 7 x64桌面与vs2010和一个虚拟框安装与单声道和monodevelop的Linux。我用vs2010编译下面的程序,并在linux虚拟机中运行它,并且它看起来不可捕捉的FileNotFoundException失败。如果我在虚拟机中编译并在Windows中运行它,它会很好。如何在Mono上运行时遇到FileNotFoundException并且缺少DLL?

问题似乎是,无法加载dll时,无法捕获的异常在Main()之前被mono抛出。有没有办法重构我的程序或强制单声道,以便我可以捕获此异常?

我正在尝试编写一个程序,该程序根据运行时可用的内容在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 
    } 

} 

} 

回答

0

您正在接触JIT编译器的实现细节。确切的时间将会抛出缺失的程序集异常,这取决于它是如何急切地将IL转换为机器码。我知道Microsoft的抖动确实是及时的,它在即将执行之前一次编译一种方法。尽管这受到是否连接调试器的影响。比如说,如果Mono编写了整个课程,你就会死在水中。在Main()可以启动之前,抖动将被抛出。

如果将Main2()放入另一个类中,它可能会更好。要做的最好的事情就是有一个可用的组件,如果有必要的话可以是一个虚拟组件

+0

将Main2放在另一个班级中并没有帮助。你说的话是有道理的,尽管扔掉一个不可捕捉的异常的概念对我来说是非常令人沮丧的。我打算把这个问题留出一段时间,看看有没有人有一个神奇的答案,但我似乎不可避免地会给你答案。谢谢。 – zope 2010-08-18 19:09:01

0

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

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

+0

在Linux上PresentationFramework是第一个触发异常的DLL。在Windows上,它是GTK-Sharp。 Winforms不在此程序中使用。程序的全部要点是让它抛出一个异常,以便我能够看到它的适当位置,因此注释掉你提到的各种代码将会使这个练习变得不可能。 如果有一个更好的方法可以让一个.exe在运行时在两个API之间进行选择,那么我就会全神贯注。 – zope 2010-08-18 19:11:53

+0

啊,所以你使用的是演示文稿框架,而不是表单?我认为这并没有太大的改变。为了让单个EXE能够运行,最好的方法是使用跨平台UI。 GTK#也适用于Windows,所以如果它不是麻烦的话,那么使用它应该适合你。我最初说的是,你得到例外的原因是系统没有按照你的预期关注'#if's,所以改变这些可能会更有帮助。不过,我并不熟悉C#预处理器。如果没有其他的工作,你可能只需要构建两次,一次用于Windows,一次用于Linux。 – ssube 2010-08-18 21:35:28

+0

它完全按照我的预期关注#ifs。他们应该强迫它总是使用错误的库。我想要例外。程序的全部要点是产生异常来捕捉它。我想在许多情况下使用这种技术从各种库中进行选择。 GTK和WPF只是一个例子。做我想做的事似乎是不可能的。 我不想强制Windows用户使用gtk。 – zope 2010-08-18 21:59:21

0

而不是依赖于引用程序集加载的懒惰,我建议你在不同的程序集中实现特定于平台的GUI,可能会实现一个通用接口。然后主程序集不会直接引用特定的GUI工具包,但会使用反射来尝试从GAC加载WPF或GTK,并基于此将使用反射来加载特定的GUI dll程序集并实例化并使用GUI实现。

喜欢的东西:

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

我可能会诉诸你所说的话。 TBH我认为我没有其他选择。我想我在这里不能选择多个答案?我想相信你们俩。 – zope 2010-08-19 17:20:07