尝试通过 mciSendString 播放 mp3 文件时出现问题 (MCIERR_CANNOT_LOAD_DRIVER)

Issue when trying to play mp3 file via mciSendString (MCIERR_CANNOT_LOAD_DRIVER)

尝试使用 mciSendString 播放 mp3 文件时,通过以下命令:

open "{FileName}" [type mpegvideo] alias {AliasName} //有和没有type mpegvideo

都试过了

play {AliasName}

我收到错误 MCIERR_CANNOT_LOAD_DRIVER : 'Unknown problem while loading the specified device driver'

在这篇 post 中读到您需要安装 MP3 编解码器,但我有一个,所以这不是问题。

四处搜索后,试图找出问题所在,我偶然发现了这个 project,它是一个使用 mciSendString 的音频播放器,并决定尝试一下,看看是否有同样的问题发生了,有趣的是它工作得很好并且可以播放 mp3 文件...那么问题是什么,为什么在我的项目中不起作用。

这是代码(这只是测试代码,如果没有足够的异常处理,请见谅):

using System;
using System.IO;
using System.Runtime.InteropServices;

namespace Test
{
    unsafe class Program
    {
        [DllImport("winmm.dll", SetLastError = true)]
        public static extern bool mciGetErrorString([In] int error, [In, Out] char[] buffer, [In] int bufferCount);

        [DllImport("winmm.dll", SetLastError = true)]
        public static extern int mciSendString([In] string command, [Optional, In, Out] char[] returnBuffer, [Optional, In] int returnBufferCount, [Optional, In] IntPtr hNotifyWindow);

        static void Main(string[] args)
        {
            Play(@"D:\Audio\simple_beat.mp3");

            Console.ReadLine();

            Close();
        }

        static void Play(string fileName)
        {
            Close();

            if (!string.IsNullOrEmpty(fileName) && File.Exists(fileName))
            {
                int error = mciSendString($"open \"{fileName}\" type mpegvideo alias RandomAudio", null, 0, IntPtr.Zero);

                if (error != 0)
                {
                    error = mciSendString($"open \"{fileName}\" alias RandomAudio", null, 0, IntPtr.Zero);

                    if (error != 0)
                    {
                        throw new MciException(error);
                    }
                }
                error = mciSendString($"play RandomAudio", null, 0, IntPtr.Zero);

                if (error != 0)
                {
                    Close();

                    throw new MciException(error);
                }
            }
        }

        static void Close()
        {
            var error = mciSendString($"close RandomAudio", null, 0, IntPtr.Zero);

            if (error != 0)
            {
                throw new MciException(error);
            }
        }

        class MciException : SystemException
        {
            public MciException(int error)
            {
                var buffer = new char[128];

                if (mciGetErrorString(error, buffer, 128))
                {
                    _message = new string(buffer);

                    return;
                }
                _message = "An unknown error has occured.";
            }

            public override string Message
            {
                get
                {
                    return _message;
                }
            }

            private string _message;
        }
    }
}

找到问题所在,mciSendString无法在控制台应用程序中打开和播放 MP3 文件,但如果应用程序是 winform,它会播放它们。

因此,如果您想通过 mciSendString 播放 MP3,您需要创建一个 winform 应用程序,如果您需要控制台而不是表单,只需将表单大小设置为零并使用 AllocConsole 创建控制台。

你的mp3文件在某个U盘里?因为当它在USB时我不能播放mp3文件,但是当它是HD时我可以..

如果您尝试在控制台项目下 运行,您可以创建一个 window 句柄并将其分配给您的 class。 VB 示例片段:

Public Class AudioPlayer : Inherits NativeWindow : Implements IDisposable
    Private piFormHandle As Integer = 0

    Sub New
        Me.CreateHandle(New CreateParams)
        piFormHandle = Me.Handle.ToInt32
    End Sub

    Public Function Play()
        mciSendString("play MyAlias from 0 notify", Nothing, 0, piFormHandle)
    End Sub

    Protected Overridable Sub Dispose(disposing As Boolean)
        If Not Me.disposedValue Then
            If disposing Then
                Me.DestroyHandle()

我使用“通知”和句柄,因此我可以捕获 MM_MCINOTIFY 并检测文件结尾:

Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)

    Const MM_MCINOTIFY As Integer = &H3B9
    Const MCI_NOTIFY_SUCCESSFUL As Integer = &H1

    Select Case (m.Msg)
        Case MM_MCINOTIFY
            Select Case m.WParam.ToInt32()
                Case MCI_NOTIFY_SUCCESSFUL
                    ' Close device, throw events...