2008-09-29 4 views
63

В коде C# вы можете поймать естественное исключение, выброшенное из глубины некоторой неуправляемой библиотеки? Если это так, вам нужно сделать что-то по-другому, чтобы поймать его или сделать стандартную попытку ... поймать его?Можете ли вы поймать собственное исключение в коде C#?

ответ

31

Вы можете использовать Win32Exception и использовать его Свойство NativeErrorCode для правильной обработки.

// http://support.microsoft.com/kb/186550 
const int ERROR_FILE_NOT_FOUND = 2; 
const int ERROR_ACCESS_DENIED = 5; 
const int ERROR_NO_APP_ASSOCIATED = 1155; 

void OpenFile(string filePath) 
{ 
    Process process = new Process(); 

    try 
    { 
     // Calls native application registered for the file type 
     // This may throw native exception 
     process.StartInfo.FileName = filePath; 
     process.StartInfo.Verb = "Open"; 
     process.StartInfo.CreateNoWindow = true; 
     process.Start(); 
    } 
    catch (Win32Exception e) 
    { 
     if (e.NativeErrorCode == ERROR_FILE_NOT_FOUND || 
      e.NativeErrorCode == ERROR_ACCESS_DENIED || 
      e.NativeErrorCode == ERROR_NO_APP_ASSOCIATED) 
     { 
      MessageBox.Show(this, e.Message, "Error", 
        MessageBoxButtons.OK, 
        MessageBoxIcon.Exclamation); 
     } 
    } 
} 
0

Если вы используете

try 
{ 

} 
catch(Exception ex) 
{ 

} 

будет перехватывать все исключения, в зависимости от того, как вы называете внешние библиотеки, вы можете получить связанное исключение ком, который инкапсулирует ошибку, но он будет ловить ошибку.

+0

Вы не можете поймать StackOverflow или OutOfMemoryException, хотя, несмотря ни на что, правильно? – core 2008-09-30 05:14:16

+0

те заканчивают ошибки, которые останавливают приложение, поэтому да, вы не можете работать с ними. – 2008-09-30 13:58:50

+7

На самом деле это не совсем правильно, это приведет к сбоям всех исключений, связанных с CLS. C++/CLI и MC++ - это языки, способные бросать исключения, не связанные с CLS. – 2011-03-25 16:47:32

9

Уровень взаимодействия между C# и собственным кодом преобразует исключение в управляемую форму, позволяя ему быть пойманным вашим кодом C#. Начиная с .NET 2.0, catch (Exception) должен поймать что-либо, кроме невосстановимой ошибки.

0

Стандартная попытка улова должна делать трюк, на который я верю.

бегает с аналогичной проблемой с System.Data исключением метания исключения SQLClient, который был неперехваченным, добавив try..catch в мой код сделал трюк в экземпляре

5

Где-то с помощью .NET Reflector я видел следующий код:

try { 
    ... 
} catch(Exception e) { 
    ... 
} catch { 
    ... 
} 

Хм, C# не позволяет бросить исключение не вытекающее из класса System.Exception. И насколько я знаю какое-либо исключение, cautch by interch marshaller завершается классом исключения, который наследует System.Exception.

Так что мой вопрос в том, можно ли поймать исключение, которое не является исключением System.Exception.

16

Поймать без() будет перехватывать исключения, отличные от CLS, включая собственные исключения.

try 
{ 

} 
catch 
{ 

} 

Смотрите правила FxCop для получения дополнительной информации http://msdn.microsoft.com/en-gb/bb264489.aspx

4

Это зависит от того, какого типа родного исключения вы говорите. Если вы ссылаетесь на исключение SEH, CLR будет делать одну из двух вещей.

  1. В случае известного кода ошибки SEH он сопоставляет его к соответствующему .Net исключения (т.е. OutOfMemoryException)
  2. В случае маркированного назначаемыми (E_FAIL) или неизвестный код будет просто выбросить пример SEHException.

Оба они будут пойманы с помощью простого блока «catch (Exception)».

Другой тип естественного исключения, который может пересекать нативную/управляемую границу, - это исключения C++. Я не уверен, как они отображаются/обрабатываются. Я предполагаю, что, поскольку Windows реализует исключения C++ поверх SEH, они просто отображаются одинаково.

3

Почти, но не совсем.Вы поймаете исключение с

try 
{ 
    ... 
} 
catch (Exception e) 
{ 
    ... 
} 

, но у вас все еще будут проблемы. Согласно MSDN для того, чтобы обеспечить исключения деструкторов называются вы должны поймать как:

try 
{ 
    ... 
} 
catch 
{ 
    ... 
} 

Это единственный способ застраховать деструктор исключение называется (хотя я не знаю, почему). Но это оставляет вам компромисс между грубой силой и возможной утечкой памяти.

Кстати, если вы используете подход (Exception e), вы должны знать различные типы исключений, которые могут возникнуть. RuntimeWrappedException - это то, к чему будет управляться любой управляемый тип без исключения (для языков, которые могут вызывать строку), а другие будут отображаться, например OutOfMemoryException и AccessViolationException. COM Interop HRESULTS или исключения, отличные от E___FAIL, будут отображаться в COMException, и, наконец, в конце вы получите SEHException для E_FAIL или любое другое неотображенное исключение.

Так что вы должны делать? Лучший выбор - это не исключать исключения из вашего неуправляемого кода! Хах. На самом деле, хотя, если у вас есть выбор, возникают барьеры и неудачи, которые делают выбор, который хуже, вероятность утечки памяти во время обработки исключений или не зная, какой тип является вашим исключением.

Смежные вопросы