Можете ли вы поймать нативное исключение в коде C #? - PullRequest
71 голосов
/ 30 сентября 2008

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

Ответы [ 8 ]

31 голосов
/ 30 сентября 2008

Вы можете использовать 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);
        }
    }
}
16 голосов
/ 30 сентября 2008

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

try
{

}
catch
{

}

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

11 голосов
/ 30 сентября 2008

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

5 голосов
/ 30 сентября 2008

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

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

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

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

5 голосов
/ 30 сентября 2008

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

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

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

Поэтому мой вопрос заключается в том, возможно ли перехватить исключение, которое не является System.Exception.

3 голосов
/ 30 сентября 2008

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

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

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

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

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

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

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

0 голосов
/ 30 сентября 2008

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

Я столкнулся с подобной проблемой с исключением System.data, выдавшим исключение sqlClient, которое было необработанным, и добавив try..catch в мой код, добившись цели в случае

0 голосов
/ 30 сентября 2008

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

try
{

}
catch(Exception ex)
{

}

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...