2009-12-26 118 views
5

我有以下的代碼部分,旨在算多少Excel的進程是當前打開:如果'Process.HasExited'引發異常,我可以認爲這個過程沒有了嗎?

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

再後來我找回伯爵在不同的點,其代碼如下所示:

int excelAppCount = OpenExcelProcessesCount(); 

這段代碼幾個月來一直運行良好。突然,今天,它始終給我一個例外,上面寫着以下內容:

Exception: ApplicationThreadException 

Message: Access is denied 

Stack Trace: 

    at System.Diagnostics.ProcessManager.OpenProcess(Int32 

的ProcessID,的Int32訪問,布爾 throwIfExited)

at System.Diagnostics.Process.GetProcessHandle(Int32 

訪問,布爾throwIfExited)

at System.Diagnostics.Process.get_HasExited() 

    etc... 

基本上,撥打Process.HasExited(在上面的堆棧跟蹤中顯示爲System.Diagnostics.Process.get_HasExited())失敗。錯誤消息「訪問被拒絕」聽起來像我沒有進程的管理權限,但現有的唯一Excel進程將在我當前用戶登錄時創建,並且用戶可以始終訪問他們自己的進程。我的.NET代碼也在完全信任下運行。

最終失敗的線路是System.Diagnostics.ProcessManager.OpenProcess(Int32 processId, Int32 access, Boolean throwIfExited)。我想知道它是否正在爲'throwIfExited'參數傳遞一個'true'的值。如果是這種情況,那麼我想我可以用一個try-catch塊保護對Process.HasExited的呼叫,並假設如果這個失敗了,那麼HasExited實際上是「真實的」。但這是一個安全的假設?

我不喜歡這樣做,因爲錯誤信息是「訪問被拒絕」。有沒有人對我如何解決這個問題有任何想法,或者我可能測試什麼以試圖弄清楚發生了什麼?

我能找到堆棧溢出的唯一類似的線程如下:Why did hasExited throw ‘System.ComponentModel.Win32Exception’?。給出的答案有:

「既然你正在做的運行方式,你只 得到上同步手柄接入, 不PROCESS_QUERY_INFORMATION訪問, 因此GetExitCodeProcess失敗,這 導致hasEnded拋出一個Win32 例外。 「

我真的不明白這個答案,不知道這是否適用於我的情況,但我想我應該提到它。如果有人認爲這可能是我面臨的情況,那麼如果有人能夠爲我澄清這個答案,我將不勝感激。 (我是一個Excel的程序員,我沒有太多的經驗與流程工作。)提前

許多感謝...

更新:

盡我所知,這是令人一種一次性的腐敗。我遇到的問題開始變得越來越奇怪,因爲完美的單元測試集開始在其他「不可能」的位置出現故障。一個簡單的重新啓動糾正了這個問題以及我面對的其他一切

我最好的猜測是我有某種奇怪的腐敗。也許ROT已經崩潰了,或者我有一個懸而未決的Excel實例,它非常腐敗,甚至'流程'操作也不一定是穩定的。沒有什麼決定性的,但這是我現在可以想到的。

對於花時間回答並幫助我的響應者,我感謝你。

+3

「我不知道,如果是的‘throwIfExited’參數‘真’的值傳遞這...這是一個安全的假設? ?」根據Reflector,HasExited爲throwIfExited傳遞了一個false值。另外,如果throwIfExited爲true,則該異常將爲InvalidOperationException,並顯示一條消息,指示進程已退出。 (對不起,我沒有你的問題的答案,但我認爲這是值得一提的,所以你沒有花時間在一個不成熟的理論。) – itowlson 2009-12-26 01:35:42

+0

謝謝,itowlson,我真的很感激信息,這肯定有幫助。 – 2009-12-26 01:44:11

回答

4

您引用的答案可能適用於您的情況。據我瞭解,它基本上是說,如果您正在查看的進程在不同的用戶帳戶下運行,那麼HasExited無法獲得確定進程是否退出所需的權限。

現在你說「存在的唯一Excel進程將在我當前用戶登錄下創建。」但是,假設情況並非如此。假設另一個用戶帳戶下有另一個Excel進程在同一個框上運行? (也許有人開始使用OLE自動化,別人的過程,並沒有得到清理或正確清理。)然後GetProcessesByName會拿起它,但HasExited會失敗。

因此,在調用OpenExcelProcessesCount()方法之前,添加一些日誌記錄以轉儲從GetProcessesByName(「Excel」)返回的所有進程的進程ID。然後針對任務管理器或您希望在您的帳戶下運行的Excel進程數量進行檢查。如果有一個ID不符合「預期的」Excel過程,那麼您可能有一個罪魁禍首。

+0

非常感謝,我非常感謝你在這裏的想法和努力。我會看一看。我沒有看到這可能是一個在任何其他登錄中創建的進程,因爲我是這臺計算機上唯一的一個,並且沒有其他帳戶。但是,我認爲Excel *的損壞/崩潰實例可能會導致此問題。我會在更多的測試後回來...... – 2009-12-26 02:22:53

+0

我最好的猜測是我有某種奇怪的腐敗。重新啓動解決了一切。我的猜測是ROT已經崩潰了,並且/或者我有一個非常腐敗的Excel實例,甚至'流程'操作也不一定穩定。沒有確鑿的結論,但這是我現在可以想到的一切...我感謝幫助。 – 2009-12-26 19:00:34

1

閱讀the documentation後:

使用此方法來創建新 過程組件陣列和準 他們與所有的進程資源 正在運行的本地計算機上的相同的可執行文件 。

它在我看來像你不需要檢查HasExited,因爲它只返回正在運行的進程。

+0

好點。我的代碼充其量只是一個競爭條件,其中'Process.HasExited'只有在通過'Process.GetProcessesByName'返回的進程在接收'Process'實例並測試它之間退出時才能返回'false' 'HasExited'。所以我現在已經去掉了'HasExited'的電話。然而,以前的神祕仍然存在,但感謝您的幫助! – 2009-12-26 19:04:48

6

如果目標進程正在運行並且進程沒有運行,Process.HasExited可以拋出一個拒絕訪問異常。 StartTime屬性也一樣。

這裏是一個博客帖子關於這個話題可能的解決方法:Bugs in System.Diagnostics.Process Class

+1

謝謝Giorgi,這是非常好的信息。 – 2011-12-29 17:59:06

+0

@MikeRosenblum:堆棧跟蹤看起來與我在博客中的一樣。 – Giorgi 2011-12-30 18:17:53

相關問題