.NET应用程序中的Vista异常"异常处理消息"

Mab*_*lah 8 windows exception windows-vista

背景

我在4.0 Framework上构建了一个VB .NET应用程序,主要功能的一部分是内置的AxWMPLib.AxWindowsMediaPlayer,它允许我们将文件路径作为URL传递给播放器,然后通过内置的媒体播放器播放.我的开发平台是Windows 7上的VS 2010 Pro.

问题

我们最近开始在多个操作系统上测试此应用程序.应用程序在多个win7机器上的Win 7上运行良好,有些用于开发其他机器.问题是我们在Vista上运行应用程序.应用程序第一次尝试在文件打开后播放它会引发错误

在此输入图像描述

它大部分时间都是这样做的,但并不总是这样,而且我已经无法建立一个模式,因为它没有抛出错误.此外,它仅针对后续文件播放的第一个文件执行此操作.它避免了Try catchs的错误处理.

研究

我对这个问题做了很多研究.我发现它似乎困扰着其他媒体播放器和网站,甚至是某些机器上的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
Run Code Online (Sandbox Code Playgroud)

目的

我希望找到一种方法来处理这个异常通过代码,潜在预览或狙击它,如果它是从我正在使用的.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
Run Code Online (Sandbox Code Playgroud)

您将看到添加名为SEM_FAILCRITICALERRORS的Const变量,这是将变量的值设置为1所必需的,在这种情况下,变量的名称非常具体,因为它与SetErrorMode方法中的标志var名称匹配,设置为true此标志禁用CriticalErrors显示.我还将.dll ext添加到了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
Run Code Online (Sandbox Code Playgroud)

现在这很重要!最初我在Ctlcontrols.play调用之后将SetErrorMode返回到oldErrMode,但发现这并没有阻止错误.我在我的win7机器上以调试模式设置我的VS并逐行逐步执行代码.我发现代码实际上没有尝试播放文件,直到子结束.这就是你看到计时器调用的原因.我设置了一个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
Run Code Online (Sandbox Code Playgroud)

最后一点需要注意的是.根据我的理解,这个过程禁止显示严重错误,所以要小心,在我的情况下,我无法找到由抛出的错误引起的任何特定错误或系统不稳定,所以我暂时禁用它以增加程序的可用性.我不建议每次遇到系统错误时都这样做,因为错误通常指向应该修复的程序中的缺陷/错误.此外,在我看来,您永远不需要永久关闭严重错误,这意味着确保在完成后重新启用它们.我希望这些信息可以帮助和欣赏那些回答或提出问题的人的时间和知识.

jor*_*are 2

根据我在网上找到的信息,这可能是由有问题的 WMP 插件、代码或显示驱动程序引起的。还发现您应该能够在 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 )
Run Code Online (Sandbox Code Playgroud)

我还没有测试过这个,所以请告诉我这是否有帮助。