2009-12-26 24 views
5

Tôi đã phần mã sau, được thiết kế để đếm có bao nhiêu quá trình Excel hiện đang mở cửa:Nếu 'Process.HasExited' ném một ngoại lệ, tôi có thể giả định rằng quá trình này đã biến mất không?

Func<int> OpenExcelProcessesCount = 
    () => System.Diagnostics.Process.GetProcessesByName("Excel") 
       .Where(p => !p.HasExited) 
       .Count(); 

Và sau đó tôi lấy số tại các điểm khác nhau, với mã như sau:

int excelAppCount = OpenExcelProcessesCount(); 

Mã này đã chạy 100% tiền phạt trong nhiều tháng. Rồi đột nhiên, ngày nay, người ta luôn đem lại cho tôi một ngoại lệ mà đọc như sau:

Exception: ApplicationThreadException 

Message: Access is denied 

Stack Trace: 

    at System.Diagnostics.ProcessManager.OpenProcess(Int32 

ProcessID, truy cập Int32, Boolean throwIfExited)

at System.Diagnostics.Process.GetProcessHandle(Int32 

truy cập, Boolean throwIfExited)

at System.Diagnostics.Process.get_HasExited() 

    etc... 

Về cơ bản, cuộc gọi đến Process.HasExited (hiển thị là System.Diagnostics.Process.get_HasExited() trong ngăn xếp ngăn xếp, ở trên) không thành công. Thông báo lỗi "Truy cập bị từ chối" giống như tôi không có đặc quyền quản trị cho quá trình này, nhưng các quy trình Excel duy nhất tồn tại sẽ được tạo trong đăng nhập người dùng hiện tại của tôi và người dùng luôn có thể truy cập các quy trình của riêng họ. Mã .NET của tôi cũng hoạt động dưới sự tin cậy hoàn toàn.

Dòng cuối cùng không thành công là System.Diagnostics.ProcessManager.OpenProcess(Int32 processId, Int32 access, Boolean throwIfExited). Tôi tự hỏi nếu nó đang được thông qua trong một giá trị của 'true' cho tham số 'throwIfExited'. Nếu đây là trường hợp, sau đó tôi giả sử rằng tôi có thể bảo vệ cuộc gọi đến Process.HasExited với một khối try-catch và giả định rằng nếu điều này không thành công HasExited là, trên thực tế, 'true'. Nhưng đây có phải là một giả định an toàn không ??

Tôi không thoải mái khi đưa ra giả định như thế này, đặc biệt là vì thông báo lỗi là "Truy cập bị từ chối". Có ai có bất kỳ ý tưởng về cách tôi có thể giải quyết này, hoặc những gì tôi có thể thử nghiệm trong một nỗ lực để tìm ra những gì đang xảy ra?

Chỉ có chủ đề tương tự mà tôi có thể tìm thấy trên Stack Overflow như sau: Why did hasExited throw ‘System.ComponentModel.Win32Exception’?. Câu trả lời cho có:

"Vì bạn đang làm runas, bạn chỉ được đồng bộ hóa truy cập trên tay cầm, không PROCESS_QUERY_INFORMATION truy cập, do đó GetExitCodeProcess thất bại, mà kết quả trong hasEnded ném một ngoại lệ Win32 . "

Tôi không thực sự hiểu câu trả lời này và không biết nếu điều này áp dụng trong trường hợp của tôi, nhưng tôi nghĩ tôi nên đề cập đến nó. Nếu bất cứ ai cảm thấy rằng có khả năng đây là tình huống mà tôi đang phải đối mặt, thì nếu ai đó có thể cố gắng làm rõ câu trả lời này cho tôi, tôi sẽ đánh giá cao điều đó. (Tôi là một lập trình viên Excel, tôi không có nhiều kinh nghiệm làm việc với các quá trình.)

Cảm ơn nhiều trước ...

Cập nhật:

tốt nhất tôi có thể nói, đây là được một tham nhũng một lần nào đó.Những vấn đề tôi phải đối mặt ngày càng trở nên kỳ lạ như những gì đã được một bộ hoàn hảo hoạt động của các bài kiểm tra đơn vị đã bắt đầu có sự cố tại các địa điểm "không thể" khác. Một khởi động lại đơn giản đã khắc phục sự cố này và mọi thứ khác mà tôi đang gặp phải.

Đoán tốt nhất của tôi là tôi đã có một số loại tham nhũng kì lạ. Có lẽ ROT đã được corupted, và/hoặc tôi đã có một trường hợp treo của Excel đã bị hỏng mà ngay cả 'Quy trình' hoạt động không nhất thiết phải ổn định. Không có gì kết luận, nhưng đây là tất cả những gì tôi có thể đoán được bây giờ.

Đối với những người trả lời đã dành thời gian trả lời và giúp tôi, tôi cảm ơn bạn.

+3

"Tôi tự hỏi nếu nó đang được thông qua trong một giá trị của 'true' cho tham số 'throwIfExited' ... Đây là một giả định an toàn không? ? " Không. Theo Reflector, HasExited chuyển giá trị false cho throwIfExited. Ngoài ra, nếu throwIfExited là true, ngoại lệ sẽ là một InvalidOperationException với một thông báo cho biết rằng quá trình đã thoát. (Xin lỗi, tôi không có câu trả lời cho câu hỏi của bạn, nhưng tôi nghĩ nó đáng nói đến điều này vì vậy bạn không dành thời gian cho một lý thuyết không hợp lý.) – itowlson

+0

Cảm ơn, itowlson, tôi thực sự đánh giá cao thông tin, điều này chắc chắn sẽ giúp. –

Trả lời

4

Câu trả lời bạn trích dẫn có thể áp dụng trong trường hợp của bạn. Theo tôi hiểu nó, về cơ bản nó nói rằng nếu quá trình bạn đang xem đang chạy dưới một tài khoản người dùng khác, thì HasExited không thể nhận được các quyền cần thiết để xác định xem quá trình đã thoát hay chưa.

Bây giờ bạn nói "các quy trình Excel duy nhất tồn tại sẽ được tạo trong đăng nhập người dùng hiện tại của tôi". Nhưng giả sử đó không phải là trường hợp. Giả sử có một quá trình Excel khác đang chạy trên cùng một hộp, dưới một tài khoản người dùng khác? (Có thể một người đã bắt đầu bởi quá trình của người khác bằng cách sử dụng OLE Automation, và không được dọn dẹp đúng cách hoặc đã treo.) Sau đó GetProcessesByName sẽ nhặt nó lên, nhưng HasExited sẽ thất bại. Vì vậy, trước khi gọi phương thức OpenExcelProcessesCount() của bạn, thêm một chút đăng nhập để kết xuất các ID tiến trình của tất cả các quy trình được trả về từ GetProcessesByName ("Excel"). Sau đó kiểm tra những điều này với Task Manager, hoặc số lượng các quá trình Excel mà bạn mong muốn được chạy trong tài khoản của bạn. Nếu có một ID ở đó không tương ứng với quy trình Excel "dự kiến", bạn có thể có thủ phạm.

+0

Cảm ơn rất nhiều, tôi thực sự đánh giá cao những suy nghĩ và nỗ lực của bạn ở đây. Tôi sẽ cho cái nhìn này. Tôi không thấy làm thế nào điều này có thể là một quá trình tạo ra trên bất kỳ đăng nhập khác, bởi vì tôi là người duy nhất trên máy này và không có tài khoản khác. Tuy nhiên, tôi nghĩ rằng một trường hợp bị hỏng/bị hỏng của Excel * có thể * đã gây ra điều này. Tôi sẽ trở lại sau khi thử nghiệm thêm ... –

+0

Tôi đoán tốt nhất là tôi đã có một số loại tham nhũng kỳ lạ. Khởi động lại đã giải quyết mọi thứ.Tôi đoán là ROT đã bị corupted, và/hoặc tôi đã có một trường hợp treo của Excel đã bị hỏng mà ngay cả các hoạt động 'Process' không nhất thiết phải ổn định. Không có gì kết luận, nhưng đây là tất cả những gì tôi có thể hình dung bây giờ ... Tôi đánh giá cao sự giúp đỡ. –

1

Sau khi đọc the documentation:

Sử dụng phương pháp này để tạo ra một loạt các thành phần Process mới và liên kết họ với tất cả các nguồn tài nguyên quá trình đang chạy cùng một tập tin thực thi trên máy tính cục bộ.

Dường như với tôi như bạn không cần phải kiểm tra HasExited, vì nó chỉ trả về các quy trình đang chạy.

+0

Điểm tốt. Mã của tôi là dư thừa ở mức tốt nhất và số tiền cho một điều kiện chủng tộc mà 'Process.HasExited' chỉ có thể trả về 'false' nếu một quá trình được trả về thông qua 'Process.GetProcessesByName' đã thoát trong micro giây giữa việc thu thập cá thể 'Process' và kiểm tra nó cho 'Đã giải quyết'. Vì vậy, bây giờ tôi đã xóa cuộc gọi đến 'Đã giải quyết'. Tuy nhiên, bí ẩn trước đó vẫn còn, nhưng cảm ơn sự giúp đỡ của bạn! –

6

Process.HasExited có thể ném một truy cập bị từ chối ngoại lệ nếu quá trình nhắm mục tiêu đang chạy cao và quá trình của bạn không phải là. Điều tương tự cũng xảy ra với thuộc tính StartTime.

Đây là một bài viết trên blog về chủ đề này với khả năng workaround: Bugs in System.Diagnostics.Process Class

+1

Cảm ơn Giorgi, đây thực sự là thông tin tốt. –

+0

@MikeRosenblum: Stacktrace cũng trông giống như một trong đó tôi có trong blog. – Giorgi

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