我的目标
我正在尝试为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 库,用于从 Python 运行时访问 .NET 程序集的功能。
- 我创建了一个 .NET 程序集来访问 WMPLib,它是 Windows SDK 的一部分,旨在以编程方式访问 WMP 的功能。WMPLib 基本上是针对 wmp.dll 的 .NET 的 COM 互操作包装器。
什么工作?
从 Python 到基于 COM 的 WMP 访问的整个链都在工作。如果我启动 Plex 媒体服务器(Python 2.7 版本)附带的嵌入式 Plex 脚本主机,我可以轻松地从 WMP 访问数据。这意味着链中的以下链接都在工作:
- Python正在为 .NET 加载 Python
- .NET 的Python正在加载我的 .NET 程序集
- 我的 .NET 程序集正在加载 WMPLib(Interop.WMPLib.dll,COM 互操作的 .NET 程序集)
- WMPLib正在成功打开和使用 wmp.dll(从 C:\Windows\System32 访问)
什么不工作?
在沙盒 Plex 插件中无法激活此链的 COM 互操作部分。同样,这个插件是用标准 Python 编写的,但是一旦沙盒代码运行,Python 执行环境就会有一些微妙的不同。从插件中运行 WMP 访问代码时出现以下异常:
COMException: Exception from HRESULT: 0xC00D1327
at WMPLib.IWMPPlayer4.get_mediaCollection()
- 在这种情况下,我知道 Python for .NET 正在工作,因为此时我已经从我的 .NET 程序集中加载并访问了其他内容。
- C:\Windows\System32位于 PATH 变量的前面。我假设 COM dll 应该通过 PATH 环境变量定位(这似乎是这样说的),但我并不完全确定这一点。 在这种独特的场景中(Python 访问 .NET 访问 COM)应该如何定位 COM 程序集是我最大的未知数之一。
问题
- Plex 插件沙箱如何更改 Python 执行环境,从而无法访问 COM 程序集?
- 在这种情况下,环境应该如何定位和访问 COM 程序集?
- 它是否需要 Plex 沙盒可能已锁定的特定权限?
也许我至少应该赢得某种奖品,因为我以一种独特的混乱方式解决了一个与众多不同技术相交的问题……
编辑 1
感谢@Paulo 下面的建议,我已经完全排除了任何与 .NET 相关的问题。我现在正在WMPLib
通过comtypes
Python 库进行所有互操作。现在我收到以下错误:
COMError: (-1072884953, None, (None, None, None, 0, None))
虽然-1072884953
是一个不同的错误代码,但稍微挖掘一下就会发现这个错误与(可能等同于?)我通过 .NET 互操作遇到的相同错误相关联(这篇文章使它看起来如此)。
所以现在我坚持的事实是:
wmp.dll
在所有情况下都在加载(@Paulo 帮助我在下面弄清楚)。- 当访问 WMP 的代码在 Plex 沙箱环境之外运行时,可以从 WMP 访问库项目。
- 当访问 WMP 的代码在 Plex 沙箱环境中运行时,无法从 WMP 访问库项目。
- 我得到的错误代码(无论是来自 .NET 还是基于 Python 的 COM 互操作)
NS_E_CURL_INVALIDPATH: The URL contains a path that is not valid.
在大多数情况下,此错误似乎与尝试播放有关。 - 这很奇怪,因为我从来没有在我的场景中播放过……我只是想打电话
wmp.mediaCollection
因此,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 沙盒如何更改执行环境的详细信息。我想我的答案就在那个方向。