2008-09-29 24 views

Trả lời

31

Bạn có thể sử dụng Win32Exception và sử dụng của nó Thuộc tính NativeErrorCode để xử lý nó một cách thích hợp.

// 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); 
     } 
    } 
} 
+6

Tôi tin rằng đây không phải là tự động, nhưng chỉ bị ném khi bạn sử dụng chữ ký P/Invoke xác định nó. Và nó được ném dựa trên một mã lỗi Win32, không phải là một ngoại lệ Win32. –

0

Nếu bạn sử dụng một

try 
{ 

} 
catch(Exception ex) 
{ 

} 

nó sẽ bắt ALL trường hợp ngoại lệ, tùy thuộc vào cách bạn gọi các thư viện bên ngoài, bạn có thể nhận được một ngoại lệ liên quan com mà đóng gói lỗi nhưng nó sẽ bắt lỗi.

+0

Mặc dù vậy, bạn không thể bắt được StackOverflow hoặc OutOfMemoryException, cho dù là gì, đúng không? – core

+0

những lỗi kết thúc, tạm dừng ứng dụng, vì vậy có bạn không thể làm việc với chúng. –

+7

Đây không phải là thực sự khá chính xác, điều này sẽ bắt tất cả các ngoại lệ tuân thủ CLS. C++/CLI và MC++ là cả hai ngôn ngữ có khả năng ném ngoại lệ không tuân thủ CLS. –

9

Lớp interop giữa C# và mã gốc sẽ chuyển đổi ngoại lệ thành biểu mẫu được quản lý, cho phép nó bị mã C# của bạn bắt. Kể từ .NET 2.0, catch (Exception) sẽ bắt được bất kỳ điều gì khác ngoài lỗi không thể khôi phục.

+3

Trong .NET 1.x, có thể cho một ngoại lệ được ném mà không lấy được từ lớp Exception, nhưng khả năng này được tắt theo mặc định trong 2.0 –

+1

thực sự? Nó để làm gì? –

+0

Tôi thực sự không biết. –

0

Một tiêu chuẩn thử bắt nên làm các trick tôi tin.

Tôi chạy vào một vấn đề tương tự với một ngoại lệ System.data ném một ngoại lệ SqlClient đó là còn tự do, thêm một try..catch vào mã của tôi đã làm các trick trong trường hợp

5

Một nơi nào đó bằng cách sử dụng NET Reflector Tôi đã nhìn thấy đoạn mã sau:

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

Hmm, C# không cho phép để ném một ngoại lệ không bắt nguồn từ lớp System.Exception. Và như xa như tôi biết bất kỳ trường hợp ngoại lệ nào của marshaller interop được bao bọc bởi lớp ngoại lệ thừa hưởng System.Exception.

Vì vậy, câu hỏi của tôi là liệu có thể bắt được ngoại lệ không phải là một System.Exception hay không.

+1

Có thể phát ra hoặc tạo ra IL để ném một vật thể tùy ý. Trình biên dịch C# sẽ không cho phép bạn làm điều đó, nhưng các trình biên dịch khác có thể, hoặc như tôi đã nói bạn có thể trực tiếp phát ra IL. Một câu lệnh catch không có kiểu nào sẽ bắt các đối tượng tùy ý cũng như các đối tượng thừa kế Exception. – technophile

16

Catch without() sẽ bắt ngoại lệ tuân thủ non-CLS bao gồm ngoại lệ gốc.

try 
{ 

} 
catch 
{ 

} 

Xem quy tắc FxCop sau để biết thêm http://msdn.microsoft.com/en-gb/bb264489.aspx

+7

Yep điều này là đúng. Chỉ cần phát hiện ra điều này bản thân mình sau một vài giờ đặc biệt gây phiền nhiễu đã dành so sánh các tập tin đăng nhập và mã và suy nghĩ tôi đã mất nó. Mặc dù vậy, câu hỏi rõ ràng là bạn có thể xác định loại ngoại lệ gốc từ bên trong khối catch rỗng không? Bạn có thể đăng nhập bất kỳ thứ gì hữu ích để xác định nguồn gốc của ngoại lệ không? – Tyson

4

Điều này phụ thuộc vào loại trừ nguồn gốc bạn đang nói về. Nếu bạn đang đề cập đến một ngoại lệ SEH thì CLR sẽ làm một trong hai điều.

  1. Trong trường hợp của một mã lỗi SEH biết nó sẽ lập bản đồ nó vào ngoại lệ Net thích hợp (ví dụ OutOfMemoryException)
  2. Trong trường hợp của một un-trí trên bản đồ (E_FAIL) hoặc mã chưa biết nó sẽ chỉ ném một ví dụ SEHException.

Cả hai trường hợp này sẽ bị chặn với khối "catch (Ngoại lệ)" đơn giản.

Loại ngoại lệ gốc khác có thể vượt qua ranh giới gốc/được quản lý là ngoại lệ C++. Tôi không chắc chắn cách họ được ánh xạ/xử lý. Tôi đoán là kể từ khi Windows thực hiện ngoại lệ C++ trên đầu trang của SEH, họ chỉ được ánh xạ theo cùng một cách.

+0

* 'Windows thực hiện ngoại lệ C++ trên đầu trang SEH' * - điều này có vẻ đúng với VC? – Wolf

3

Hầu như, nhưng không hoàn toàn.Bạn sẽ bắt ngoại lệ với

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

nhưng bạn vẫn sẽ có vấn đề tiềm năng. Theo MSDN, để đảm bảo destructors ngoại lệ được gọi là bạn sẽ phải bắt như:

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

Đây là cách duy nhất để đảm bảo một destructor ngoại lệ được gọi là (mặc dù tôi không chắc chắn lý do tại sao). Nhưng điều đó khiến bạn phải cân bằng sức mạnh vũ phu so với rò rỉ bộ nhớ có thể xảy ra.

Ngẫu nhiên, nếu bạn sử dụng phương pháp (Ngoại lệ e), bạn nên biết các loại ngoại lệ khác nhau mà bạn có thể gặp phải. RuntimeWrappedException là bất kỳ loại ngoại lệ được quản lý nào sẽ được ánh xạ tới (đối với các ngôn ngữ có thể ném một chuỗi), và một số khác sẽ được ánh xạ, chẳng hạn như OutOfMemoryException và AccessViolationException. COM Interop HRESULTS hoặc các ngoại lệ khác với E___FAIL sẽ ánh xạ tới COMException, và cuối cùng ở cuối bạn có SEHException cho E_FAIL hoặc bất kỳ ngoại lệ chưa được ánh xạ nào khác.

Vì vậy, bạn nên làm gì? Lựa chọn tốt nhất là không ném ngoại lệ từ mã không được quản lý của bạn! Hah. Thực sự mặc dù nếu bạn có một sự lựa chọn, đưa ra rào cản và thất bại mà làm cho sự lựa chọn đó là tồi tệ hơn, một cơ hội của một rò rỉ bộ nhớ trong xử lý ngoại lệ, hoặc không biết loại ngoại lệ của bạn là gì.

Các vấn đề liên quan