【问题标题】:C++ - Running Windows Media Player from Console Application - COMC++ - 从控制台应用程序运行 Windows Media Player - COM
【发布时间】:2014-10-09 20:21:52
【问题描述】:

我正在尝试使用 Windows Media Player 播放电影,稍后将添加一些其他功能。 以下是我写的代码:

const CLSID CLSID_WindowsMediaPlayer = {0x6BF52A52, 0x394A, 0x11d3, {0xB1, 0x53, 0x00, 0xC0, 0x4F, 0x79, 0xFA, 0xA6 } };
HRESULT         hr;
IWMPPlayer      *pMediaPlayer = NULL;

hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
if(FAILED(hr))
{
    std::cout << "ERR -- Could not Initialize COM engine for you" << std::endl;
    return 0;
}

hr = CoCreateInstance(CLSID_WindowsMediaPlayer, NULL, CLSCTX_INPROC_SERVER, IID_IDispatch, (void**)&pMediaPlayer);
if(FAILED(hr))
{
    std::cout << "ERR - Could not get WMPPlayer Interface Pointer" << std::endl;
    return 0;
}
std::cout << "Got MediaPlayer Pointer" << std::endl;

IWMPSettings    *pMediaPlayerSettings = NULL;
hr = pMediaPlayer->get_settings(&pMediaPlayerSettings);
if(FAILED(hr))
{
    std::cout << "ERR - Could not get WMPSettings Interface Pointer" << std::endl;
    ReleaseInterfaces((IUnknown**)&pMediaPlayer);
    return 0;
}
std::cout << "Got MediaPlayerSettings Pointer" << std::endl;

hr = pMediaPlayerSettings->put_autoStart(VARIANT_TRUE);
if(FAILED(hr))
{
    std::cout << "ERR - Could not put auto_start to true" << std::endl;
    ReleaseInterfaces((IUnknown**)&pMediaPlayerSettings);
    ReleaseInterfaces((IUnknown**)&pMediaPlayer);
    return 0;
}
std::cout << "Have put it to autostart" << std::endl;

hr = pMediaPlayerSettings->put_volume(50);
if(FAILED(hr))
{
    std::cout << "ERR - Could not put volume" << std::endl;
    ReleaseInterfaces((IUnknown**)&pMediaPlayerSettings);
    ReleaseInterfaces((IUnknown**)&pMediaPlayer);
    return 0;
}
std::cout << "Have put volume to listen-able" << std::endl;

hr = pMediaPlayer->put_URL(L"C:\\background.mp3");
if(FAILED(hr))
{
    std::cout << "ERR - Could not set URL" << std::endl;
    ReleaseInterfaces((IUnknown**)&pMediaPlayerSettings);
    ReleaseInterfaces((IUnknown**)&pMediaPlayer);
    return 0;
}
std::cout << "Have set URL" << std::endl;

到目前为止一切都很好。但文件永远不会播放。经过进一步调查,我发现WMPPlayState永远不会变成wmppsPlaying,所以我测试了文件是否使用WMPOpenState打开,但在这里我总是得到wmposOpeningUnknownURL。我首先认为这可能是因为我将文件放在需要管理员权限的C: 中,但使用其他位置也会产生相同的结果。我检查了我使用 put_URL 设置的 URL 是否真的被放置,是的,get_URL 给出了我设置的 URL。我还测试了不同的文件和格式。

此外,Windows Media Player 没有打开!

【问题讨论】:

    标签: c++ windows-7 com windows-media-player


    【解决方案1】:

    你可以直接得到IWMPPlayer4的接口,使用起来更方便,像这样:

    IWMPPlayer4 *pMediaPlayer;
    
    CoCreateInstance(CLSID_WindowsMediaPlayer, NULL, CLSCTX_ALL, IID_IWMPPlayer4, (void**)&pMediaPlayer);
    pMediaPlayer->openPlayer(_bstr_t(L"C:\\background.mp3"));
    

    【讨论】:

      【解决方案2】:
        hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
      

      这是一个很常见的选择。我们看不到您的其余代码,但鞋子合脚。它要求你做 other 对 STA 线程来说是硬性要求的事情。您必须发送message loop。不这样做会导致各种问题,死锁并不少见。是的,状态不会改变,WMP 中的工作线程和你的公寓线程之间的信号是 borken,因为你没有抽水。

      您在 GUI 应用程序中得到一个消息循环,例如选择 Win32 Project 项目模板,而不是 Win32 控制台应用程序模板。或者添加代码,样板为:

      MSG msg;
      while(GetMessage(&msg, NULL, 0, 0) > 0)
      {
          TranslateMessage(&msg);
          DispatchMessage(&msg);
      }
      

      请注意你没有得到一个窗口,你要求 CLSCTX_INPROC_SERVER。换句话说,WMP 在您的程序内部以进程内方式运行。获得一个窗口需要使用 ActiveX 托管,如果没有 MFC 或 Winforms 等类库的重要帮助,您通常不会想要解决这个问题。也许您真正想要做的是在进程外运行它,以便它可以显示自己的窗口?

      【讨论】:

      • 谢谢您的回答先生。 CLSCTX_INPROC_SERVER 在那里进行反复试验。如果我使用CLSCTX_LOCAL_SERVERCoCreateInstace 会失败并显示Class Not Registered。可能这是另一个问题,但是如果没有ActiveX,自动化就不可能吗?我认为它或多或少类似于办公自动化。任何进一步的指示?因为我们需要一个窗口。
      • 进一步的研究表明这可能是因为 MediaPlayer 注册了 COM+ 服务器,那么 MediaPlayer 自动化从原始 COM 实现的可能性有多大?我找到了一种方法,通过从组件服务面板中删除 COM+ 条目可能会解决问题,但这不是一个好方法,因为这意味着客户端 PC 上的媒体播放器将无法使用 COM+,我隐约知道它用于网络 COM
      猜你喜欢
      • 2017-06-19
      • 2011-10-13
      • 2020-10-20
      • 2010-11-19
      • 1970-01-01
      • 1970-01-01
      • 2011-01-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多