当源是 https uri 时,如何使 wpf MediaElement 播放

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25081956/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 12:15:25  来源:igfitidea点击:

How to make a wpf MediaElement play when its Source is a https uri

c#wpfnullreferenceexceptionmediaelement

提问by Cristi Moldovan

In a wpf standalone application (.exe) I have included a MediaElement in the MainWindow

在 wpf 独立应用程序 (.exe) 中,我在 MainWindow 中包含了一个 MediaElement

<Window x:Class="Media.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Main Window" Height="350" Width="525">
    <Grid>
        <MediaElement x:Name="Player" Stretch="Uniform" LoadedBehavior="Manual" UnloadedBehavior="Stop"/>
    </Grid>
</Window>

and from the code behind I set its Sourceto any https Uri:

从后面的代码中,我将其设置Source为任何 https Uri:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        var source = new Uri("https://stream_which_can_be_opened_with_windows_media_player.com", UriKind.Absolute);
        Player.Source = source;
        Player.Play();
    }
}

When the Play()method is called a NullReferenceExceptionis thrown instead of playing the media content. MediaElementis initialized, the NullReferenceExceptionis thrown from the Play()method, see below.

当该Play()方法被调用时,NullReferenceException会抛出一个而不是播放媒体内容。MediaElement被初始化,NullReferenceExceptionPlay()方法中抛出,见下文。

The same Uri for the video can be opened in Windows Media Player (File->Open Url).

可以在 Windows Media Player 中打开视频的相同 Uri(文件->打开 Url)。

The issue seems to be in MediaPlayerState.OpenMediamethod (an object which the MediaElementuses internally) which tries to check if appDeploymentUri retrieved from SecurityHelper.ExtractUriForClickOnceDeployedApphas the scheme HTTPS. The application is not deployed with ClickOnce(it has a standalone installer) and the appDeploymentUri is null, hence the NullReferenceException.

问题似乎出在MediaPlayerState.OpenMedia方法(MediaElement内部使用的对象)中,该方法试图检查从中检索的 appDeploymentUriSecurityHelper.ExtractUriForClickOnceDeployedApp是否具有 HTTPS 方案。应用程序没有部署ClickOnce(它有一个独立的安装程序)并且 appDeploymentUri 为空,因此NullReferenceException.

This is from PresentationFramework.dll, System.Windows.Media.MediaPlayerState.OpenMedia

这是来自 PresentationFramework.dll, System.Windows.Media.MediaPlayerState.OpenMedia

    if (SecurityHelper.AreStringTypesEqual(uriToOpen.Scheme, Uri.UriSchemeHttps))
    {
        // target is HTTPS. Then, elevate ONLY if we are NOT coming from HTTPS (=XDomain HTTPS app to HTTPS media disallowed)

        //source of the issue
        Uri appDeploymentUri = SecurityHelper.ExtractUriForClickOnceDeployedApp();
        //appDeploymentUri is null
        if (!SecurityHelper.AreStringTypesEqual(appDeploymentUri.Scheme, Uri.UriSchemeHttps))

Does anyone have any about a workaround/solution to make it work?

有没有人有任何解决方法/解决方案使其工作?

采纳答案by Erti-Chris Eelmaa

I have been working with MediaElement quite few times, and I can honestly say it's a piece of shit and has more bugs than any other WPF component I've encountered. Not only has it bugs, but it's lacking a lot of features that Silverlight has. HTTPS works with Silverlight.

我已经与 MediaElement 合作过好几次了,老实说,我可以说这是一团糟,比我遇到的任何其他 WPF 组件都有更多的错误。它不仅有缺陷,而且缺少 Silverlight 的许多功能。HTTPS 适用于 Silverlight。

I went through code and I did not see the way to change it. Perhaps there is some MAD reflection hack which would allow you to do it, but that's hacking and I don't recommend that. Ps, it seems like a genuine bug, perhaps let the Microsoft guys know about it.

我浏览了代码,但没有看到更改它的方法。也许有一些 MAD 反射黑客可以让您这样做,但那是黑客行为,我不建议这样做。Ps,这好像是一个真正的bug,也许让微软的人知道吧。

The easiest solution would be to make a "memory webserver" using OWIN. You can then stream through http://localhost:1337and wrap the underlying https:// content. The https content would still be safe though, since you are streaming it from "memory webserver" and no "real" webrequests are ever made. It should still be efficient & secure.

最简单的解决方案是使用 OWIN 制作“内存网络服务器”。然后,您可以流式传输http://localhost:1337并包装底层 https:// 内容。不过,https 内容仍然是安全的,因为您是从“内存网络服务器”流式传输它的,并且从未发出过“真实”的网络请求。它仍然应该是高效和安全的。