2010-03-26 2 views
5

Я новичок в Silverlight, и я делаю некоторые тесты. С моим текущим тестом я пытаюсь отобразить в реальном времени текущее содержимое буфера обмена. Но есть странное поведение с этим кодом:Silverlight 4 исключение безопасности буфера обмена «доступ запрещен»?

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: Я бы поставил на проблему потока: р

ответ

4

Доступ к буферам обмена в приложении с частичным доверием (в браузере) Приложение Silverlight (сценарий, к которому вы, вероятно, ссылаетесь выше), ограничено. Свойство GetText доступно только в сценариях, которые определяет время выполнения Silverlight. Ваш пример идеален - например, нажатием кнопки. Однако таймер отправки не инициируется пользователем, поэтому свойство генерирует исключение (это особенно важно в контексте приложения в браузере, которое может быть большой дырой в безопасности, если вы можете создать приложение Silverlight, которое просто тихо запустилось в браузер, просматривая обновления буфера обмена пользователя без их ведома).

Дополнительную информацию см. Здесь clipboard documentation.

+0

Спасибо. Есть ли способы обойти это ограничение? Я не хочу взломать, но это может быть незаменимой особенностью для приложения, которое я хочу построить ... –

+0

@Niklaos: Единственный способ обойти это ограничение - установить приложение как приложение для браузера с повышенным доверять. – AnthonyWJones

+1

Также обратите внимание, что буфер обмена Silverlight ограничен только текстом. – WiredPrairie

1

Вы пробовали это:

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

редактировать

После быстрого поиска, представляется, что Clipboard доступен только в ответ на действие пользователя, см. here и here.

В режиме частичного доверия (режим по умолчанию для приложений Silverlight на базе браузера состоялся), Silverlight также ограничивает клипборда доступ к своим двум ключа API, GetText и SetText. Эти API могут быть вызваны только из контекста , который определяется средой выполнения Silverlight , чтобы быть в ответе к инициированному пользователем действию. Например, для доступ к буферам обмена действителен из обработчика для Click или Событие KeyDown. Напротив, буфер обмена доступ недействителен из обработчика для Загружен или из конструктора, и попытки доступа исключают.

+1

Dispatcher.Invoke генерирует ошибку компиляции. BeginInvoke компилируется, но одно и то же исключение генерируется одной строкой:/Любые другие идеи? –

1

Если ваш единственный вариант - использовать таймер, то не делайте этого вообще. Clipboad - это общий ресурс, и вы будете поднимать ошибки «не удается открыть буфер обмена» в других программах, поскольку они пытаются получить доступ к буферу. то есть пользователь копирует что-то из WinWord, WinWord пытается открыть буфер обмена, но не может, потому что вы заблокировали его, пока вы его изучаете.

+0

Полезно знать! Я не хочу использовать таймер (это довольно уродливо), но есть ли другие способы? Кажется, Microsoft забыла событие «ClipboardUpdated»: p –

+0

Не знаю, как я не знаю Silverlight. У меня только что есть много опыта на другом конце такого рода вещей. Посмотрите на любую ссылку на Clipboard Viewer или WM_DrawClipboard в документах API. Кроме того, поймите, что ваш вызов GetText() приведет к отправке сообщения WM_RenderFormat в приложение, которое выполнило копирование (если они используют «Delayed Rendering», что делают большинство крупных приложений), поэтому вы будете добавлять к своим неприятностям таким образом а также, в значительной степени гарантируя, что все, что вы только что пытались захватить, заставит приложение-приложение хотеть снова открыть буфер обмена. И не получается. –

+1

Microsoft предоставила обновленное сообщение в буфер обмена для собственных приложений Win32 (WM_CLIPBOARDUPDATE). Но для кросс-платформенного приложения Silverlight у вас нет доступа к этому сообщению/функциональности (особенно в контексте приложения в браузере, что будет большой проблемой безопасности, если вы можете написать код, который просто сидел тихо в браузере, просматривая обновления буфера обмена пользователя без их ведома). – WiredPrairie

2

Просто введите Clipboard.ContainsText() вместо текста. Разрешен метод ContainsText!

0

Здравствуйте это работает для меня, но только в IE Microsoft.LightSwitch.Threading.Dispatchers.Main.BeginInvoke(() => HtmlPage.Window.Eval("window.clipboardData.setData('Text','testtestest')"));

просто использовать GetData метод