2009-02-01 11 views
6

Làm cách nào tôi có thể phân bổ tài nguyên khi quá trình bị giết bởi, ví dụ: Trình quản lý tác vụ? Có cách nào để gọi một hàm trước khi quá trình bị đóng không?Tài nguyên giao dịch khi chấm dứt quá trình

+0

Tôi đã trả lời nhận xét của bạn bằng cách chỉnh sửa câu trả lời của tôi – ChrisW

Trả lời

8

Thực sự bạn không thể làm gì nếu quá trình của bạn bị giết. Theo định nghĩa, giết chết một quá trình chỉ là - giết chết nó. Quá trình này không có cơ hội để chạy bất kỳ mã nào. Điều này là rất nhiều "theo thiết kế".

Hãy tưởng tượng rằng bạn có thể đăng ký một thói quen được gọi khi quá trình của bạn bị người dùng giết (hoặc bởi một quy trình khác). Nó sẽ làm gì? Tất cả các chủ đề khác trong quá trình của bạn sẽ ở trong trạng thái không xác định, Bạn sẽ đồng bộ hóa với chúng bằng cách nào? Hãy nhớ rằng, ý tưởng là quá trình cần phải bị giết.

Kịch bản khác thậm chí còn khó khăn hơn: mã của bạn là lành tính và cố gắng làm điều đúng - ví dụ: dọn dẹp và trở thành công dân hệ thống tốt. Một số mã không phải là. Hãy tưởng tượng những gì một lợi ích cho một tác giả phần mềm độc hại nó sẽ là nếu hệ điều hành cho phép mã được chạy cho một quá trình đã bị giết. Nó sẽ là đủ xấu cho các quá trình độc hại đang chạy với các đặc quyền người dùng chuẩn, và hoàn toàn khủng khiếp đối với bất kỳ hoạt động nào có quyền quản trị.

Xử lý ngoại lệ và xử lý ngoại lệ có cấu trúc quan trọng sẽ không giải quyết được vấn đề cơ bản này.

Ở phía trên, hệ điều hành sẽ giải phóng tất cả các tài nguyên mà nó biết khi quá trình của bạn bị giết, cụ thể là bộ nhớ và đối tượng hạt nhân. Những thứ đó sẽ không bị rò rỉ. Nhưng nhà thám hiểm không biết về quá trình của bạn để nó không thể dọn dẹp được.

Một cách để giải quyết vấn đề này là có quy trình giám sát theo dõi các quy trình khác của bạn và làm sạch nó. Bạn có thể làm điều này với một quy trình đơn giản, hoặc với một dịch vụ. Bạn cũng có thể xem xét một số loại mở rộng vỏ có chủ đề riêng của nó đã làm điều tương tự.

1

Về mặt lý thuyết, O/S nên xử lý tài nguyên sau khi quá trình này bị giết. Bạn đang nghĩ đến loại tài nguyên nào?


Edit:

Ok, nó kinda khó khăn để giải thích. Tôi đang sử dụng một thư viện được gói một số chức năng hệ điều hành để quản lý một số phần mở rộng Shell. Khi ứng dụng đóng mà không gọi một cách rõ ràng các phương thức thích hợp, tất cả các trình thám hiểm bị đóng băng và tôi cần phải khởi động lại nó.

Bất kỳ DLL không được quản lý nào (theo tài liệu) được cho là được gọi với sự kiện DLL_PROCESS_DETACH; tuy nhiên, sự kiện DLL_PROCESS_DETACH này không được gọi khi quá trình chấm dứt qua API TerminateProcess.

Googling cho these terms bật lên The Old New Thing : Why can't you trap TerminateProcess? mà nói, "Khi bạn giết với TerminateProcess, không có nhiều mã sử dụng chế độ sẽ chạy trong quá trình đó. Nó đã biến mất."

Bởi vì tất cả những gì bạn đang cố gắng làm việc với (tức là .NET, Explorer, Shell, COM) đang diễn ra ở chế độ người dùng, tôi nghĩ câu trả lời là không có cách nào để làm những gì bạn muốn. Thay vào đó, có lẽ có một cách khác: ví dụ: bằng cách thêm mã vào tiện ích mở rộng Shell của bạn để chúng nhận ra liệu quy trình của bạn có được tuân thủ hay không.

+0

Ok, thật khó để giải thích. Tôi đang sử dụng một thư viện được gói một số chức năng hệ điều hành để quản lý một số phần mở rộng Shell. Khi ứng dụng đóng mà không gọi một cách rõ ràng các phương thức thích hợp, tất cả các trình thám hiểm bị đóng băng và tôi cần phải khởi động lại nó. – user57528

+0

DLL_PROCESS_DETACH không được chuyển tới DllMain khi chấm dứt do TerminateProcess gây ra. –

+0

Cảm ơn Barry: Tôi sẽ chỉnh sửa câu trả lời của mình cho phù hợp. – ChrisW

0

Bạn có thể thử gói toàn bộ quy trình của mình trong câu lệnh thử/cuối cùng (bạn đặt công cụ deallocation trong mệnh đề cuối cùng), nhưng trong một số trường hợp thậm chí không đủ.

Thực ra, tôi nghĩ bạn có thể khởi chạy một chuỗi nền từ quá trình của bạn để thực hiện tất cả các công cụ và Thread.Join() với chuỗi chính của bạn để nếu có gì đó sai trong chủ đề con, chủ đề chính vẫn có thể để có được những điều đúng đắn. Tất nhiên, điều này sẽ không hoạt động nếu toàn bộ quá trình bị chấm dứt vì một lý do nào đó.

Bạn cũng có thể khởi chạy tiến trình con và gọi Process.WaitForExit() nhưng tôi không chắc liệu điều liên quan đến shell của bạn có thể hoạt động với phương pháp đa tiến trình hay không.

4

Không có cách nào để thực thi mã tùy ý khi chấm dứt trong một quá trình sắp bị giết bởi một cuộc gọi đến TerminateProcess, chẳng hạn như Trình quản lý tác vụ hoặc một tiện ích quy trình khác như TSKILL hoặc TASKKILL.

Không có trình hoàn tất quan trọng, cũng không phải finalizers bình thường, cũng không cố gắng/cuối cùng khối, và chắc chắn không chỉ đối tượng thực hiện IDisposable có thể gây ra mã được thực hiện trong kịch bản này. Ngay cả các sự kiện tháo rời DLL cũng sẽ không được gọi từ một quá trình chấm dứt thông qua TerminateProcess.

Điều tốt nhất bạn có thể làm là sử dụng quy trình giám sát giám sát quy trình gốc của bạn và thực thi mã có liên quan khi quá trình gốc bị chấm dứt.