2010-08-18 83 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