【问题标题】:Silverlight Out-of-Browser application will not close using MainWindow.Close methodSilverlight Out-of-Browser 应用程序不会使用 MainWindow.Close 方法关闭
【发布时间】:2012-06-29 02:47:32
【问题描述】:

我有一个 Silverlight 5.1.10411.0 Out-of-Browser 应用程序,它是 NOT trusted,我正在尝试使用 App.Current.MainWindow.Close 方法关闭应用程序。根据文档,如果以下条件之一为真,我只能使用此机制:

  • 这是一个受信任的应用程序(我的应用程序不是这样)
  • 在 Application.Startup 事件完成之前(我的应用程序不是这样)
  • 响应用户发起的操作,例如,在按钮 Click 事件处理程序中(这就是我想要开始的工作)

在我试图让它工作的过程中,我让事情变得非常简单,并直接在按钮单击事件处理程序后面的代码中调用该方法,如下所示,但它没有任何效果。

void closeButton_Click(object sender, RoutedEventArgs e)
{
    var mainWindow = Application.Current.MainWindow;
    mainWindow.Close();
}

当我附加调试器并设置“抛出异常时中断”时,我可以看到异常

SecurityException: 无法访问属性或方法调用 允许,除非应用程序具有提升的权限,或者代码 是通过用户发起的操作调用的。

任何想法为什么我的代码不被视为用户发起的操作?

我尝试在 XAML 和代码隐藏中附加事件处理程序(不是同时)

 <Button x:Name="closeButton" Content="Close" Click="closeButton_Click" />

 closeButton.Click += closeButton_Click;

没有成功。我已经非常仔细地阅读了User-Initiated Events 文档,看不出为什么我的代码不被认为是用户启动的。我已经在调试和发布模式以及没有成功连接调试器的情况下尝试过这个。如果我将“在浏览器外运行时需要提升信任”更改为 true,则关闭调用将按预期工作。

我已经重新定义了我的应用程序要求来解决这个问题,但我真的很想了解我做错了什么;-)

更新SonOfPirate 的回答表明此方法的文档不准确,但我不相信。使用反射工具dotPeek抛出异常的方法是

private void CheckForPermissions()
{
  if (!Application.Current.HasElevatedPermissions && !XcpImports.IsUserInitiatedAction() && Application.Current.ApplicationStarted)
    throw new SecurityException(Resx.GetString("Window_AccessNotAllowed"));
}

我觉得这有点令人困惑,所以我模拟了代码并为它编写了单元测试,如 gist 所示,从结果中可以看出,我应该能够从不受信任的应用程序调用 close ,只要它是用户启动的。

安全异常消息

除非应用程序具有提升的权限,或者代码是通过用户启动的操作调用的,否则不允许访问属性或方法调用。

还表明它应该是可能的,所以我回到问题 - 为什么这段代码不被认为是用户启动的?

【问题讨论】:

  • 你有几个窗口吗?
  • 不,只有一个 MainWindow。
  • 您是否尝试过使用按钮的命令?不应该改变任何东西。
  • 我尝试使用一个实现ICommand 的类和按钮命令参数,它不会改变行为。我仍然得到相同的 SecurityException。
  • 我认为你可以提交一个错误然后:(

标签: silverlight silverlight-5.0


【解决方案1】:

当您声明“只有在以下条件之一为真时才能使用此机制时,错误出现在第一段:”再仔细阅读 MS 文档,您会发现他们没有说“之一”这些条件。以下是Close method 的 MS 参考页面中的确切文本:

只有在以下情况下才能调用该方法:

  • 响应用户启动的操作,例如,在按钮 Click 事件处理程序中。
  • 在 Application.Startup 事件完成之前(即在 IApplicationService.StartService 方法中,IApplicationLifetimeAware.Starting 方法或 Startup 事件处理程序)。
  • 在受信任的应用程序中。

如您所见,您需要提高信任度。

更新

我承认 Microsoft 使用的措辞有点误导,前两种情况中的任何一种都需要与第三种情况结合使用。如果措辞更准确,也许会更清楚:

在以下任一情况下,您只能在受信任的应用程序中调用此方法:

  • 响应用户启动的操作,例如,在按钮 Click 事件处理程序中。
  • 在 Application.Startup 事件完成之前(即在 IApplicationService.StartService 方法、IApplicationLifetimeAware.Starting 方法或 Startup 事件处理程序)。

【讨论】:

  • 我已经考虑过所有案例都需要为真,而不是其中任何一个,但这意味着您只能调用“在 Application.Startup 事件完成之前”的方法。情况并非如此,您绝对可以在启动事件之后在受信任的应用程序中调用该方法。如果您使用反射工具查看 Window.Close 方法,您可以看到对 this.CheckForPermissions(); 的调用,并且该实现仅在不受信任且不是用户启动且应用程序已启动时才抛出异常。
  • 我认为你可能是对的,尽管我会使用比“有点误导”更强的语言,至少我会放弃 bit :-)
  • 我观察到的行为与您修改的文档版本相匹配(即只能从受信任的应用程序调用),但 CheckForPermissons 代码的反映版本和异常消息表明这应该并非如此 - 也就是说,如果它是用户启动的,您应该能够从不受信任的应用程序中调用它。我已经用这个细节更新了这个问题。接下来我将在具有普通 silverlight 运行时而不是开发人员运行时的机器上尝试此操作。
  • 有趣。我同意 CheckForPermissions 方法绝对允许不受信任的应用程序,但如果没有提升的权限,我永远无法让它工作。
【解决方案2】:

如何在 Silverlight 中提升 webBrowser 控件的权限:

1-http://msdn.microsoft.com/en-us/library/gg192793%28v=vs.96%29.aspx 主题: 启用浏览器内受信任的应用程序

2-http://www.johnpapa.net/digitally-signing-a-xap-silverlight/ 主题: 对 XAP Silverlight 进行数字签名

3-http://chainding.wordpress.com/2012/09/19/silverlight-5-trusted-applications/ 主题: 添加所需的注册表设置 签署您的 XAP 文件 部署证书

并确保将签名证书部署在本地机器和当前用户的受信任发布者中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-03
    • 1970-01-01
    • 2011-01-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多