Как поймать FilenotFoundException при запуске на Mono и DLL отсутствует?
-
29-09-2019 - |
Вопрос
У меня есть рабочий стол Windows 7 x64 с VS2010 и установка виртуальной коробки Linux с Mono и Monodevelop. Я составляю следующую программу с VS2010 и запускаю ее в виртуальной машине Linux, и она не работает с, казалось бы, невозможным FilenotFoundException. Если я составляю его в виртуальной машине и запускаю его в Windows, он отлично работает.
Похоже, что проблема заключается в том, что моно бросается невозможным исключением перед Main (), когда невозможно загрузить DLL. Есть ли способ реструктурировать мою программу или приступить к моно, чтобы я мог поймать это исключение?
Я пытаюсь написать одну программу, которая имеет интерфейс в 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
}
}
}
Решение
Вы подвергаете себя деталям реализации JIT-компилятора. Точное время, которое он бросит исключение для пропущенной сборки, зависит от того, насколько с нетерпением он переводит IL в машинный код. Я знаю, что дрожание Microsoft действительно в свое время, он собирает по одному методу за раз, непосредственно перед тем, как он собирается выполнить. Хотя это влияет на то, прилагается ли отладчик. Вы мертвы в воде, если моно, скажем, собирает весь класс. Джиттер бросится до начала Main ().
Может быть, это будет работать лучше, если вы положите Main2 () в другой класс. Лучшее, что можно сделать, это просто иметь сборку, манекен, если это необходимо.
Другие советы
Какой DLL не найден? Я предполагаю, судя по вашему кодексу, это, вероятно, Winforms. Я не совсем знаком с препроцессором C#, но я думаю #if __MonoCS__
Может быть более полезным (или может действовать только) как препроцессор, то есть он не меняется во время выполнения. Вы можете попытаться определить __MonoCS__
Для моно сборки в настройках проекта и запустите это (я думаю, что VS не определяет это по умолчанию, так что, вероятно, это, вероятно, пытается работать с Winforms в любом случае).
Еще одна вещь, которую нужно попробовать, - это комментировать using System.Windows
и весь его связанный код (просто используя путь GTK/Mono) и проверяйте, строится ли это на Windows и работает на обоих. Если это так, то вы сузили возможные проблемы до того, что включают, и оттуда должно быть легче решить.
Вместо того, чтобы в зависимости от лени нагрузки с ссылочной сборкой, я предлагаю вам реализовать ваши графические интерфейсы для конкретной платформы в разных сборках, возможно, реализуя общий интерфейс. Основная сборка затем не будет иметь прямых ссылок на конкретные наборы инструментов графического интерфейса, но будет использовать отражение, чтобы попытаться загрузить WPF или GTK из GAC, и в зависимости от того, что это будет использовать отражение для загрузки определенной сборки GUI DLL и создания экземпляра и использования реализации GUI Анкет
Что-то вроде:
- ProgramName.exe - содержит
Main
точка входа,IPlatformGui
, и логика, общая всеми платформами - ProgramName.gtk.dll - содержит
GtkGui : IPlatformGui
- ProgramName.wpf.dll - содержит
WpfGui : IPlatformGui