2012-04-05 63 views
8

在.NET應用程序「異常處理消息」中的Vista異常

背景

我已經在4.0 Framework上構建了一個VB .NET應用程序,主要功能的一部分是構建在AxWMPLib.AxWindowsMediaPlayer中,它允許我們傳遞一個文件路徑作爲播放器的URL,然後通過內置的媒體播放器播放。我的開發平臺是Windows 7上的VS 2010 Pro。

問題

我們最近已經開始在多個操作系統上測試此應用程序。該應用程序在多個win7機器上的Win 7上運行良好,有些用於其他開發。問題是我們在Vista上運行應用程序。在第一次應用程序嘗試已被打開後,它會拋出一個錯誤

播放文件它做到這一點大部分時間,但並非總是如此,我一直無法建立它幾次沒有拋出錯誤的模式。此外,它只對第一個播放的文件執行此操作,而不是後續文件。而且它避免了嘗試捕獲錯誤處理。

研究

我對這個問題做了很多研究。我發現它似乎困擾其他媒體播放器和網站,甚至在某些機器上播放WMP。一些文章指向特定的Windows KB更新,另一些則建議運行修復磁盤來修復潛在的不良dll。我已經嘗試了許多這樣的失敗,因爲問題依然存在於我必須測試的兩臺Vista機器上。

代碼

這裏是方法,當出現此錯誤時

Public Sub playSelected(ByVal fileStr As String) 
    If File.Exists(fileStr) Then 
     Debugging.DebugPrint(" Play: " & fileStr) 
     MediaPlayer.URL = fileStr 
     Try 
      MediaPlayer.Ctlcontrols.play() 
     Catch ex As Exception 
      MessageBox.Show("Could Not play the selected File please try again. Exception : " + ex.Message) 
     End Try 
    Else 
     Debugging.DebugPrint(" File Does not Exist: " & fileStr) 
    End If 
End Sub 

目的

我希望能找到一種方法來處理通過代碼,潛在預覽此異常或狙擊它,如果它是被稱爲從我使用的.NET控件之一拋出。如果可能的話,我寧願通過代碼來處理。如果某人也有關於此特定錯誤的其他信息,那麼也會受到歡迎。

分辨率

隨着信貸jornare的信息,推動在正確的方向,我將解釋自己的決定,並低於其背後的代碼,希望它幫助。

首先,我不得不修改推薦的答案,以幾種不同的方式。以下兩行是在調用上面的playSelected方法的類中聲明的。

Public Declare Function SetErrorMode Lib "kernel32.dll" (ByVal uMode As System.UInt32) As System.UInt32 
Private Const SEM_FAILCRITICALERRORS As System.UInt32 = &H1 

,您會看到另外const的變量命名SEM_FAILCRITICALERRORS的,這是必要的變量的值設置爲1,在這種情況下,變量的名稱是非常特殊的,因爲它標誌匹配變種SetErrorMode方法中的名稱設置爲true時,此標誌禁用顯示CriticalErrors。我還將.dll分機添加到了Lib調用中,儘管它可能不是必需的。

下面是我的新playSelected方法

Public Sub playSelected(ByVal fileStr As String) 
    If File.Exists(fileStr) Then 
     If isVista Then 
      oldErrMode = SetErrorMode(SEM_FAILCRITICALERRORS) 
     End If 
     Debugging.DebugPrint(" Play: " & fileStr) 
     MediaPlayer.URL = fileStr 
     Try 
      MediaPlayer.Ctlcontrols.play() 
     Catch ex As Exception 
      MessageBox.Show("Could Not play the selected File please try again. Exception : " + ex.Message) 
     End Try 
     If isVista Then 
      criticalFailureTimer.Interval = 2000 
      criticalFailureTimer.AutoReset = False 
      criticalFailureTimer.Start() 
     End If 
    Else 
     Debugging.DebugPrint(" File Does not Exist: " & fileStr) 
    End If 

End Sub 

現在這是很重要的!最初我調用ctlcontrols.play調用SetErrorMode回到oldErrMode,但發現這並不能防止錯誤。我在我的win7機器上將調試模式設置爲調試模式,逐行執行代碼。我發現代碼實際上並沒有嘗試播放文件,直到子結束。這就是您看到計時器呼叫的原因。我設置了一個2秒計時器給自己一個緩衝區,以便它可以在錯誤模式設置正確的情況下開始播放過程。下面是我用於計時器消逝事件的代碼

'in my Constructor 
If My.Computer.Info.OSFullName.Contains("Vista") Then 
    isVista = True 
    AddHandler criticalFailureTimer.Elapsed, AddressOf criticalTimerExpired 
End If 
'end of Constructor portion 

Private Sub criticalTimerExpired(sender As Object, e As ElapsedEventArgs) 
    SetErrorMode(oldErrMode) 
End Sub 

我會爲此付出最後一次警告。根據我的理解,此過程禁止顯示嚴重錯誤,因此請小心,在我的情況下,我無法找到由拋出的錯誤導致的任何特定錯誤或系統不穩定,因此我暫時禁用此功能以增加程序的可用性。我不建議在每次出現系統錯誤時都這樣做,因爲錯誤指向程序中應該修復的缺陷/錯誤。另外,在我看來,你永遠不需要永久關閉嚴重錯誤,也就是說,當你完成之後,確保你將它們重新開啓。我希望這些信息能夠幫助和了解那些回答或投票表決問題的人的時間和知識。

+3

+1表示您的研究=) – 2012-04-05 19:28:38

+0

只是要確定:你是說這個Try/Catch確實不*捕獲異常? – egrunin 2012-04-05 19:32:49

+0

正確,這個錯誤獨立於我的try/catch而發生。 – Madullah 2012-04-05 19:35:05

回答

2

從我在網絡上發現它可能是由錯誤的WMP插件,codek或顯示驅動程序引起的。 還發現您應該能夠通過在WMP開始加載媒體文件之前調用Windows API函數SetErrorMode(SEM_FAILCRITICALERRORS)來抑制此錯誤。

所以,對於VB類似:

'declare 
Private Declare Function SetErrorMode Lib "kernel32" (ByVal wMode As Long) As Long 

'call it 
Dim oldErrMode As Long 
oldErrMode = SetErrorMode(SEM_FAILCRITICALERRORS) 

'Do your stuff here 

'Set it back 
SetErrorMode(oldErrMode) 

我沒有測試過這一點,所以讓我知道如果這有助於。

+0

就像一個人站起來,我相信這個想法正在工作/將工作。我不得不調整一些東西,而且我仍在努力,我會給予信貸,並在我有工作後發表我的最終答案,不想給你電臺的沉默,謝謝你的幫助。 – Madullah 2012-04-23 17:54:43

+0

使用SetErrorMode方法以編程方式工作,任何未來的知識Seekers在我的描述中看到Resolution部分。 – Madullah 2012-04-23 20:42:55

+0

甜蜜:)很高興幫助 – jornare 2012-04-24 06:47:39