2008-08-04 59 views
22

Tôi đang duy trì ứng dụng .NET 1.1 và một trong những điều tôi đã được giao nhiệm vụ là đảm bảo người dùng không thấy bất kỳ thông báo lỗi không thân thiện nào.Xử lý ngoại lệ chưa xử lý trong .NET 1.1

Tôi đã thêm bộ xử lý vào Application.ThreadExceptionAppDomain.CurrentDomain.UnhandledException, được gọi. Vấn đề của tôi là hộp thoại báo lỗi CLR chuẩn vẫn được hiển thị (trước khi trình xử lý ngoại lệ được gọi).

Jeff nói về vấn đề này trên blog của mình herehere. Nhưng không có giải pháp. Vậy cách chuẩn trong .NET 1.1 là gì để xử lý các trường hợp ngoại lệ chưa đọc và hiển thị một hộp thoại thân thiện?

Phản hồi của Jeff được đánh dấu là câu trả lời đúng, vì liên kết mà anh cung cấp có thông tin đầy đủ nhất về cách thực hiện những gì cần thiết.

Trả lời

11

Ồ, trong Windows Forms, bạn chắc chắn sẽ có thể làm cho nó hoạt động. Điều duy nhất bạn phải xem ra là những điều xảy ra trên các chủ đề khác nhau.

Tôi có một bài báo cũ Mã dự án ở đây mà nên giúp đỡ:

User Friendly Exception Handling

3

Đây có phải là ứng dụng bảng điều khiển hoặc ứng dụng Windows Forms không? Nếu đó là ứng dụng giao diện .NET 1.1, thật đáng buồn, theo thiết kế - nó được xác nhận bởi một MSFT dev trong second blog post you referenced:

BTW, trên máy 1.1 của tôi ví dụ từ MSDN có đầu ra dự kiến; nó chỉ là dòng thứ hai không hiển thị cho đến khi bạn đã đính kèm một trình gỡ rối (hay không). Trong v2, chúng tôi đã lật những thứ xung quanh để sự kiện UnhandledException kích hoạt trước khi trình gỡ lỗi đính kèm, dường như điều mà hầu hết mọi người mong đợi.

Có vẻ như .NET 2.0 làm điều này tốt hơn (cảm ơn lòng tốt), nhưng thành thật mà nói, tôi không bao giờ có thời gian để quay lại và kiểm tra.

1

Đó là ứng dụng Windows Forms. Các trường hợp ngoại lệ được bắt bởi Application.ThreadException làm việc tốt, và tôi không nhận được hộp ngoại lệ .NET xấu xí (OK để chấm dứt, Hủy để gỡ lỗi? Ai đã nghĩ ra điều đó?).

Tôi đã nhận được một số ngoại lệ không bị phát hiện và kết thúc với sự kiện AppDomain.UnhandledException gây ra sự cố. Tôi nghĩ rằng tôi đã bắt gặp hầu hết những ngoại lệ đó, và bây giờ tôi đang hiển thị chúng trong hộp lỗi tốt đẹp của chúng tôi.

Vì vậy, tôi sẽ chỉ phải hy vọng không có một số trường hợp khác có thể khiến các ngoại lệ không bị xử lý bởi Application.ThreadException.

4

AppDomain.UnhandledException là một kiện, không phải là một ngoại lệ xử lý toàn cầu. Điều này có nghĩa là, vào thời điểm nó được nâng lên, ứng dụng của bạn đã bị trục trặc, và không có gì bạn có thể làm, ngoại trừ việc dọn dẹp và ghi lỗi.

Điều xảy ra sau hậu trường là: Khung phát hiện ngoại lệ, đi lên ngăn xếp cuộc gọi lên đầu, không tìm thấy trình xử lý nào có thể khôi phục từ lỗi, vì vậy không thể xác định xem có an toàn để tiếp tục thực hiện hay không .Vì vậy, nó bắt đầu trình tự tắt máy, và khởi động sự kiện này như một sự lịch sự cho bạn để bạn có thể trả tiền tôn trọng của bạn cho quá trình đã cam chịu của bạn. Điều này xảy ra khi một ngoại lệ được bỏ mặc trong chủ đề chính.

Không có giải pháp một điểm cho loại lỗi này. Bạn cần phải đặt một trình xử lý ngoại lệ thực (một khối catch) ở phía trên của tất cả các nơi xảy ra lỗi này và chuyển tiếp nó đến (ví dụ) một phương thức/lớp xử lý toàn cục sẽ xác định xem nó có an toàn hay không loại ngoại lệ và/hoặc nội dung.

Chỉnh sửa: Có thể tắt (= hack) cơ chế báo cáo lỗi được tích hợp trong Windows để hộp thoại "crash and burn" bắt buộc không hiển thị khi ứng dụng của bạn bị hỏng. Tuy nhiên, điều này sẽ có hiệu lực đối với tất cả các ứng dụng trong hệ thống chứ không phải của riêng bạn.

5

Unhandled ngoại lệ hành vi trong một 1.x NET ứng dụng Windows Forms phụ thuộc vào:

  • Các loại chủ đề mà ném ngoại lệ
  • Cho dù đó xảy ra trong khi xử lý thông điệp cửa sổ
  • Cho dù một debugger đã được đính kèm vào quá trình
  • Cài đặt đăng ký DbgJitDebugLaunchSetting
  • Cờ jitDebugging trong App.Config
  • Cho dù bạn overrode Windows Forms ngoại lệ handler
  • Cho dù bạn xử lý sự kiện ngoại lệ của CLR
  • Giai đoạn của mặt trăng

Hành vi mặc định của ngoại lệ unhandled là:

  • Nếu ngoại lệ xảy ra trên chủ đề chính khi bơm thông điệp cửa sổ, nó bị chặn bởi trình xử lý ngoại lệ của Windows Forms.
  • Nếu ngoại lệ xảy ra trên luồng chính khi bơm thông báo cửa sổ, nó sẽ chấm dứt quá trình ứng dụng trừ khi nó bị chặn bởi trình xử lý ngoại lệ Windows Forms.
  • Nếu ngoại lệ xảy ra trên một hướng dẫn sử dụng, threadpool, hoặc thread finalizer, nó bị nuốt chửng bởi CLR.

Các điểm tiếp xúc cho một ngoại lệ unhandled là:

  • Windows Forms xử lý ngoại lệ.
  • Công tắc đăng ký gỡ lỗi JIT DbgJitDebugLaunchSetting.
  • Sự kiện ngoại lệ CLR không được xử lý.

Windows Form built-in xử lý ngoại lệ nào sau đây theo mặc định:

  • Catches một ngoại lệ unhandled khi:
    • ngoại lệ là trên thread chính và không debugger đính kèm.
    • ngoại lệ xảy ra trong quá trình xử lý tin nhắn cửa sổ.
    • jitDebugging = false trong App.Config.
  • Hiển thị hộp thoại cho người dùng và ngăn chặn việc chấm dứt ứng dụng.

Bạn có thể tắt hành vi sau bằng cách đặt jitDebugging = true trong App.Config. Nhưng hãy nhớ rằng đây có thể là cơ hội cuối cùng của bạn để ngừng chấm dứt ứng dụng. Vì vậy, bước tiếp theo để bắt một lỗi nào đó được đăng ký cho sự kiện Application.ThreadException, ví dụ .:

Application.ThreadException += new 
Threading.ThreadExceptionHandler(CatchFormsExceptions); 

Lưu ý các thiết lập DbgJitDebugLaunchSetting dưới HKEY_LOCAL_MACHINE \ Software.NetFramework registry. Điều này có một trong ba giá trị mà tôi biết:

  • 0: hiển thị hộp thoại người dùng yêu cầu "gỡ lỗi hoặc chấm dứt".
  • 1: cho phép ngoại lệ thông qua để CLR xử lý.
  • 2: khởi chạy trình gỡ lỗi được chỉ định trong khóa đăng ký DbgManagedDebugger.

Trong Visual Studio, bạn vào menu cụTùy chọnDebuggingJIT để thiết lập phím này để 0 hoặc 2. Nhưng giá trị là 1 thường tốt nhất là trên một người dùng cuối của máy móc. Lưu ý rằng khoá đăng ký này được thực hiện trước sự kiện ngoại lệ CLR chưa được xử lý.

Sự kiện cuối cùng này là cơ hội cuối cùng để bạn đăng nhập ngoại lệ chưa được xử lý. Nó được kích hoạt trước khi các khối Cuối cùng của bạn đã thực thi. Bạn có thể chặn sự kiện này như sau:

AppDomain.CurrentDomain.UnhandledException += new 
System.UnhandledExceptionEventHandler(CatchClrExceptions);