2011-05-10 5 views
17

¿Cómo puedo obtener el texto del portapapeles en un hilo no estático? Tengo una solución pero estoy tratando de obtener la manera más limpia/más corta posible. Los resultados aparecen como una cadena vacía al llamarlo normalmente.C# Clipboard.GetText()

Respuesta

7

intento de añadir el ApartmentStateAttribute a su principal método

[STAThread] 
static void Main() { 
    //my beautiful codes 
} 
+0

No creo que esta sea la manera prevista. – BitKFu

+0

+1 para // mis hermosos códigos –

2

Usted no puede; debe especificar el STAThread attribute.

Nota:

ThreadStateException

El hilo actual no está en modo de apartamento de subproceso único (STA). Agregue el STAThreadAttribute al método Principal de su aplicación.

5

No sé cuáles son sus definiciones de limpio o corto, pero si está dispuesto a utilizar la plena confianza, puede simplemente P/invocar las funciones nativas del portapapeles para evitar los problemas de subprocesamiento. He aquí un programa completo para imprimir el texto en el portapapeles:

using System; 
using System.Runtime.InteropServices; 

namespace PasteText 
{ 
    public static class Clipboard 
    { 
     [DllImport("user32.dll")] 
     static extern IntPtr GetClipboardData(uint uFormat); 
     [DllImport("user32.dll")] 
     static extern bool IsClipboardFormatAvailable(uint format); 
     [DllImport("user32.dll", SetLastError = true)] 
     static extern bool OpenClipboard(IntPtr hWndNewOwner); 
     [DllImport("user32.dll", SetLastError = true)] 
     static extern bool CloseClipboard(); 
     [DllImport("kernel32.dll")] 
     static extern IntPtr GlobalLock(IntPtr hMem); 
     [DllImport("kernel32.dll")] 
     static extern bool GlobalUnlock(IntPtr hMem); 

     const uint CF_UNICODETEXT = 13; 

     public static string GetText() 
     { 
      if (!IsClipboardFormatAvailable(CF_UNICODETEXT)) 
       return null; 
      if (!OpenClipboard(IntPtr.Zero)) 
       return null; 

      string data = null; 
      var hGlobal = GetClipboardData(CF_UNICODETEXT); 
      if (hGlobal != IntPtr.Zero) 
      { 
       var lpwcstr = GlobalLock(hGlobal); 
       if (lpwcstr != IntPtr.Zero) 
       { 
        data = Marshal.PtrToStringUni(lpwcstr); 
        GlobalUnlock(lpwcstr); 
       } 
      } 
      CloseClipboard(); 

      return data; 
     } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      Console.WriteLine(Clipboard.GetText()); 
     } 
    } 
} 
+0

Tantas limitaciones en el uso de la clase ClipBoard .NET, esta es la mejor solución que encontré, gracias. –

14

me gustaría añadir un método de ayuda que se puede ejecutar una acción como un subproceso STA dentro de un subproceso MTA principal. Creo que esa es probablemente la forma más limpia de lograrlo.

class Program 
{ 
    [MTAThread] 
    static void Main(string[] args) 
    { 
     RunAsSTAThread(
      () => 
      { 
       Clipboard.SetText("Hallo"); 
       Console.WriteLine(Clipboard.GetText()); 
      }); 
    } 

    /// <summary> 
    /// Start an Action within an STA Thread 
    /// </summary> 
    /// <param name="goForIt"></param> 
    static void RunAsSTAThread(Action goForIt) 
    { 
     AutoResetEvent @event = new AutoResetEvent(false); 
     Thread thread = new Thread(
      () => 
      { 
       goForIt(); 
       @event.Set(); 
      }); 
     thread.SetApartmentState(ApartmentState.STA); 
     thread.Start(); 
     @event.WaitOne(); 
    } 
}