从Plex插件访问WMP的COMException(使用Python for .NET)

时间:2014-07-14 05:23:02

标签: python .net com wmp plex

我的目标

我正在尝试为Plex Media Server (PMS)创建一个插件,该插件将与WMP(Windows Media Player)连接,以获取有关Windows媒体库项目的元数据。

设置

  • PMS使用Python 2.7作为其主要脚本宿主。 Plex插件是 用Python编写,虽然它们以沙盒容量运行。不幸的是,关于这个沙盒功能的界限到底有什么令人遗憾的小文档。
  • 我决定使用Python for .NET访问Windows SDK以与WMPLib连接。 Python for .NET(http://pythonnet.github.io/)是一个Python 用于从内部访问.NET程序集的功能的库 Python运行时。
  • 我创建了一个.NET程序集来访问WMPLib 是Windows SDK的一部分,旨在以编程方式访问 WMP的功能。 WMPLib基本上是一个COM Interop包装器 .NET针对wmp.dll。

什么工作?

从Python开始通过基于COM的WMP访问的整个链正在运行。如果我启动Plex Media Server附带的嵌入式Plex脚本主机(Python 2.7的一个版本),我可以随时访问WMP中的数据。这意味着链中的以下链接都在起作用:

  • Python 加载.NET for .NET
  • Python for .NET 加载我的.NET程序集
  • 我的.NET程序集 加载WMPLib(Interop.WMPLib.dll,一个用于COM Interop的.NET程序集)
  • WMPLib 成功打开并使用wmp.dll(从C:\ Windows \ System32访问)

什么不起作用?

在沙盒Plex插件中激活此链的COM Interop部分 not 。同样,这个插件是用标准的Python编写的,但是一旦沙盒代码运行,Python的执行环境就会略有不同。从插件中运行WMP访问代码时出现以下异常:

COMException: Exception from HRESULT: 0xC00D1327
   at WMPLib.IWMPPlayer4.get_mediaCollection()
  • 在这种情况下,我知道Python for .NET正在运行,因为此时我已经加载并访问了.NET程序集中的其他内容。
  • C:\ Windows \ System32 位于PATH变量的前面。我假设COM dll应该通过PATH环境变量定位(This似乎这么说),但我并不完全确定。 如何在这个独特的场景中定位COM程序集(Python访问.NET访问COM)是我最大的未知之一

问题

  1. Plex插件沙箱如何改变Python执行环境,以便访问COM程序集不再有效?
  2. 在这种情况下,如何定位和访问COM程序集?
  3. 是否需要Plex沙箱可能已锁定的特定权限?
  4. 也许我至少应该以一种独特的混乱方式来解决与许多不同技术相交的问题,从而获得某种奖励......

    编辑1

    由于@ Paulo的建议,我完全排除了任何与.NET相关的问题。我现在通过WMPLib Python库与comtypes进行互操作。现在我收到以下错误:

    COMError: (-1072884953, None, (None, None, None, 0, None))
    

    虽然-1072884953是一个不同的错误代码,但是稍微挖掘一下就会发现这个错误与我通过.NET互操作获得的错误(可能等同于?)相关联({{3}使它看起来如此)。

    所以现在我坚持的事实是:

      在所有情况下
    1. wmp.dll都在加载(@Paulo帮助我解决了这个问题 在下面)。
    2. 当访问WMP的代码在Plex沙箱环境之外运行时,可以从WMP访问库项目。
    3. 当在Plex沙箱环境中运行访问WMP的代码时,无法从WMP访问库项目。
    4. 我得到的错误代码(无论是来自.NET还是基于Python的COM互操作是NS_E_CURL_INVALIDPATH: The URL contains a path that is not valid.在大多数情况下,此错误似乎与尝试回放有关。
    5. 这很奇怪,因为在我的情景中,我从未得到过回放......我只是试图拨打wmp.mediaCollection
    6. 因此,Plex沙箱在这种情况下似乎是关键。还有什么想法吗?

      编辑2

      最低限度,这是失败所需的代码:

      from comtypes.client import CreateObject
      
      wmp = CreateObject("{6BF52A52-394A-11d3-B153-00C04F79FAA6}")
      collection = wmp.mediaCollection
      

      collection = wmp.mediaCollection是错误发生的地方。

      因此,确实没有传递任何可能导致失败的参数。重申一下,这个代码在一般的Python 2.7上下文中运行良好。它只在Plex插件沙箱中失败。我不知道如何获得有关Plex沙箱如何改变执行环境的详细信息。我想象我的答案就在那个方向。

1 个答案:

答案 0 :(得分:0)

让我直截了当,如果我错了,请纠正我:

  • 您有一个正在运行的Python 2.7实例,Plex媒体服务器

  • 您正在使用Python for .NET将.NET加载到您的流程中

  • 您正在.NET中加载WMPLib,一个导入的COM互操作程序集,通过Python for .NET使用Windows Media Player库

让我们清楚这一点:

  • 0xC00D1327 is NS_E_CURL_INVALIDPATH

      

    网址包含无效的路径。

    这似乎是合法的对象错误,而不是COM错误。

  • DLL search order与它没什么关系,因为wmp.dll在每个提供的类的InProcServer32注册表项下注册了一个完整路径,这才是最重要的。

    事实上,正如您所说,如果您已达到这一点,那么加载.NET程序集或COM无法找到DLL显然不是问题。

现在,问题:

  1. 由于错误似乎是合法的,您可能无法访问媒体集(Internet区域?),或者WMP未正确注册/安装,或者某些编解码器丢失或未正确注册/安装等。

    你在加入WMP的是什么?尝试使用基本的东西,例如本地.WAV,.MP3,.AVI和.MPG文件,然后尝试更高级的格式,例如MPEG4编码的视频,或者可能是远程位置。

  2. 你应该尝试更直接的方法,虽然我不能保证哪个更好:win32com (part of pywin32)comtypes

    很久以前,因为我已经看过它们,所以请注意这一点:使用comtypes,你可以使用你的COM对象,就像常规Python对象的属性和方法一样,而win32com似乎更倾向于通过运行时名称调度来做事。

    至少你会打击你真正需要忍受的东西(Python),而不是加载.NET甚至不需要它(WMP)。

  3. 我不知道沙盒的含义是什么,但我的猜测是它只是一个仅限Python的沙箱,而不是限制操作系统使用的东西。


  4. 编辑:您是否提供了一个文件名(例如C:\ path \ to \ file.mp4),其中需要一个URL(file:/// C:/path/to/file.mp4),反之亦然?我想你必须显示失败的代码以及提供的值。