Silverlight 4剪贴板安全异常 "access is not allowed"?

5

我是Silverlight的新手,正在进行一些测试。在我的当前测试中,我尝试实时显示当前剪贴板内容。但是这段代码存在一些奇怪的行为:

namespace SilverlightTest
{
public partial class MainPage : UserControl
{
    private Timer _timer;

    public MainPage()
    {
        InitializeComponent();
        var dispatcher_timer = new DispatcherTimer {Interval = new TimeSpan(0, 0, 0, 5)};
        dispatcher_timer.Tick += new EventHandler(timer_Callback);
        dispatcher_timer.Start();
    }

    private void timer_Callback(object state, EventArgs eventArgs)
    {
        current_clip_board.Content = Clipboard.GetText();
    }

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        current_clip_board.Content = Clipboard.GetText();
    }
}
}

按钮事件和定时器事件应该执行完全相同的动作。 但是它们并不一样!按钮可以正常工作,并将剪贴板文本设置到标签中,但是定时器会抛出异常:

不允许访问剪贴板

问题是:为什么呢? :)
谢谢。
PS:我会打赌是线程问题。 :p
5个回答

4
在部分信任(浏览器内)的Silverlight应用程序中,剪贴板访问受到限制。 GetText属性只能在Silverlight运行时确定由用户启动的情况下访问。您的示例非常完美--例如通过单击按钮。但是,计时器调度不是用户启动的,因此该属性会抛出异常(特别是在浏览器内应用程序的上下文中,如果您可以创建一个静默运行于浏览器中的Silverlight应用程序,监视用户的剪贴板更新而不被发现,这将是一个很大的安全漏洞)。有关更多详细信息,请参见此clipboard documentation

谢谢。有什么方法可以绕过这个限制吗?我不想使用黑客手段,但这可能是我想要构建的应用程序所必需的功能... - Nicolas Guillaume
@Niklaos:绕过这个限制的唯一方法是将应用程序安装为具有提升信任的离线浏览器应用程序。 - AnthonyWJones
1
请注意,Silverlight 剪贴板仅限于文本。 - WiredPrairie

2

只需触发Clipboard.ContainsText()而不是Text。方法ContainsText是允许的!


1

你试过这个吗:

private void timer_Callback(object state, EventArgs eventArgs) 
{
    Dispatcher.Invoke(new System.Threading.ThreadStart(delegate()
    {
        current_clip_board.Content = Clipboard.GetText(); 
    }
} 

编辑

经过快速搜索,似乎 Clipboard 仅在响应用户操作时才可用。请参见 此处此处

在部分受信任的环境中(这是面向基于 Silverlight 的浏览器托管应用程序的默认模式),Silverlight 还将剪贴板访问限制为其两个关键 API GetText 和 SetText。这些 API 只能从由 Silverlight 运行时确定为响应于用户发起的操作的上下文中调用。例如,剪贴板访问是在 Click 或 KeyDown 事件的处理程序内有效的。相比之下,在 Loaded 处理程序或构造函数中剪贴板访问无效,访问尝试会引发异常。


1
Dispatcher.Invoke 会生成编译错误。BeginInvoke 能够编译通过,但是在同一行代码会产生相同的异常 :/ 还有其他的想法吗? - Nicolas Guillaume

1
如果你唯一的选择是使用计时器,那么最好不要这样做。剪贴板是一个共享资源,当其他程序尝试访问剪贴板时,你会引发“无法打开剪贴板”的错误。例如,用户从WinWord复制了某些内容,WinWord尝试打开剪贴板,但由于你正在检查它而将其锁定,因此无法打开。

很好知道! 我不想使用计时器(它看起来很丑),但还有其他方法吗?微软似乎忘了“ClipboardUpdated”事件 :p - Nicolas Guillaume
没有头绪,因为我不懂Silverlight。我只是在这种情况下有很多经验。在API文档中查找任何与Clipboard Viewer或WM_DrawClipboard有关的参考。此外,请了解您的GetText()调用将导致发送一个WM_RenderFormat消息到执行复制操作的应用程序(如果它们使用“延迟渲染”,大多数大型应用程序都会这样做),因此您也将通过几乎保证刚刚尝试抓取的任何内容,使提供应用程序想要再次打开剪贴板。并失败。 - Chris Thornton
1
微软向本地Win32应用程序提供了剪贴板更新消息(WM_CLIPBOARDUPDATE)。 但是,对于跨平台的Silverlight应用程序,您无法访问此消息/功能(尤其是在浏览器应用程序的上下文中,如果您可以编写静默坐在浏览器中监视用户剪贴板更新的代码,这将是一个很大的安全问题)。 - WiredPrairie

0

你好,这段代码在IE浏览器中可以正常工作:

Microsoft.LightSwitch.Threading.Dispatchers.Main.BeginInvoke(() => HtmlPage.Window.Eval("window.clipboardData.setData('Text','testtestest')"));

只需要使用getData方法即可。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接