2010-03-26 10 views
5

Soy nuevo en Silverlight y estoy haciendo algunas pruebas. Con mi prueba actual trato de mostrar en tiempo real el contenido actual del Portapapeles. Pero hay un comportamientos extraños con este código:Silverlight 4 Clipboard Security Exception "no se permite el acceso"?

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(); 
    } 
} 
} 

El Evento botón y el evento de temporizador se supone que debe hacer exactamente la misma acción. ¡Pero no es así! El botón funciona bien y establecer el texto del portapapeles en la etiqueta, pero el temporizador una excepción:

acceso Portapapeles no está permitido

La pregunta es: ¿por qué? :)

Gracias.

PS: Yo apostaría por un problema de rosca: p

Respuesta

4

Acceso al portapapeles, en una aplicación de confianza parcial (en el explorador) de Silverlight (el escenario al que probablemente hace referencia anteriormente), está restringido. Solo se puede acceder a la propiedad GetText en escenarios que el tiempo de ejecución de Silverlight haya sido iniciado por el usuario. Su ejemplo es perfecto: con un clic de botón, por ejemplo. Sin embargo, un temporizador de despacho no es iniciado por el usuario, por lo que arroja una excepción (esto es especialmente importante dentro del contexto de una aplicación en el navegador, lo que podría ser un gran agujero de seguridad si pudieras crear una aplicación Silverlight que acabara de ejecutarse silenciosamente en el navegador, mirando las actualizaciones del portapapeles del usuario sin su conocimiento).

Vea esto clipboard documentation para más detalles.

+0

Gracias. ¿Hay alguna forma de eludir esta restricción? No quiero un truco, pero esta podría ser una característica indispensable para la aplicación que quiero construir ... –

+0

@Niklaos: La única forma de evitar esta restricción es tener la aplicación instalada como una aplicación fuera del navegador con una elevada confianza. – AnthonyWJones

+1

También tenga en cuenta que el portapapeles de Silverlight está limitado a solo texto. – WiredPrairie

1

Has probado esto:

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

edición

Después de una búsqueda rápida, parece que Clipboard sólo está disponible en respuesta a una acción del usuario, vea here y here.

En confianza parcial (el modo predeterminado para aplicaciones basadas en Silverlight navegador-organizada), Silverlight también restringe el acceso al portapapeles sus dos clave API GetText y SetText. Estas API solo se pueden invocar desde un contexto que se determina mediante el tiempo de ejecución de Silverlight en la respuesta a una acción iniciada por el usuario. Para el ejemplo , el acceso al portapapeles es válido desde un controlador para un evento KeyDown Click o . Por el contrario, el acceso al Portapapeles no es válido desde un controlador para Cargado o desde un constructor, y los intentos de acceso arrojan excepciones.

+1

Dispatcher.Invoke generar un error de compilación. BeginInvoke compila pero la misma línea genera la misma excepción:/¿Alguna otra idea? –

1

Si su única opción es usar un temporizador, entonces no lo haga en absoluto. Clipboad es un recurso compartido y vas a generar errores de "no se puede abrir el portapapeles" en otros programas mientras intentan acceder al portapapeles. es decir, el usuario copia algo de WinWord, WinWord intenta abrir el portapapeles, pero no puede, porque lo tiene bloqueado mientras lo examina.

+0

¡Es bueno saberlo! No quiero usar un temporizador (es bastante feo), pero ¿hay otras formas? Parece que Microsoft olvidó el evento "ClipboardUpdated": p –

+0

No tengo idea, ya que no conozco Silverlight. Tengo mucha experiencia en el otro extremo de este tipo de cosas. Busque cualquier tipo de referencia a Clipboard Viewer o WM_DrawClipboard, en los documentos API. Además, comprenda que su llamada a GetText() causará que se envíe un mensaje WM_RenderFormat a la aplicación que realizó la copia (si usan "Delayed Rendering", que es lo que hacen la mayoría de las aplicaciones grandes), de modo que agregará sus problemas de esa manera. también, al garantizar que lo que acaba de tratar de capturar hará que la aplicación proveedora quiera abrir el portapapeles nuevamente. Y falla –

+1

Microsoft proporcionó el mensaje actualizado del portapapeles a las aplicaciones Win32 nativas (WM_CLIPBOARDUPDATE). Pero, para una aplicación multiplataforma de Silverlight, no tiene acceso a este mensaje/funcionalidad (especialmente dentro del contexto de una aplicación en el navegador, lo que sería un gran problema de seguridad si pudiera escribir código que simplemente se sentó silenciosamente en el navegador, mirando las actualizaciones del portapapeles del usuario sin su conocimiento). – WiredPrairie

2

Simplemente active Clipboard.ContainsText() en lugar de Texto. ¡El método ContainsText está permitido!

0

Hola esto funciona para mí, pero sólo en IE Microsoft.LightSwitch.Threading.Dispatchers.Main.BeginInvoke(() => HtmlPage.Window.Eval("window.clipboardData.setData('Text','testtestest')"));

sólo tiene que utilizar el método getData

Cuestiones relacionadas