8

背景

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

问题

我们最近开始在多个操作系统上测试这个应用程序。该应用程序在多台 win7 机器上的 Win 7 上运行良好,有些用于开发,有些则不用于开发。问题是当我们在 Vista 上运行应用程序时。应用程序在打开文件后第一次尝试播放文件时会抛出错误

在此处输入图像描述

它在大多数情况下都会这样做,但并非总是如此,而且在几次它没有引发错误的情况下,我一直无法建立模式。此外,它只对它播放的第一个文件执行此操作,而不是对后续文件执行此操作。并且它避开了用于错误处理的 Try 捕获。

研究

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

您将看到添加了名为 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

现在这很重要!最初我在 ctlcontrols.play 调用后将 SetErrorMode 恢复为 oldErrMode,但发现这并没有阻止错误。我在我的 win7 机器上将我的 VS 设置为调试模式,并逐行执行代码。我发现代码直到 sub 结束后才真正尝试播放文件。这就是您看到计时器调用的原因。我设置了一个 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

最后一个警告,我会给出这个。据我了解,此过程会禁用显示严重错误,因此请注意,在我的情况下,我无法找到由引发的错误引起的任何特定错误或系统不稳定,因此我暂时禁用此功能以增加程序的可用性。我不建议您每次遇到系统错误时都这样做,因为该错误通常指向程序中应该修复的缺陷/错误。此外,在我看来,您永远不需要永久关闭严重错误,这意味着确保在完成后重新打开它们。我希望这些信息能帮助并感谢那些回答或支持该问题的人的时间和知识。

4

1 回答 1

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 )

我还没有测试过这个,所以让我知道这是否有帮助。

于 2012-04-15T19:22:57.250 回答