¿Cómo copio el contenido de una cadena al portapapeles en C#?




.net clipboard (6)

Desearía que SetText fuera así de fácil, pero hay algunas trampas con las que tiene que lidiar. Debe asegurarse de que el subproceso en el que lo llama se esté ejecutando en la STA. A veces puede fallar con un error de acceso denegado y luego trabajar segundos después sin problemas, algo que ver con los problemas de tiempo de COM en el portapapeles. Y si se accede a su aplicación a través del escritorio remoto, el acceso al portapapeles es incompleto. Utilizamos un método centralizado para manejar todos los escenarios de tesis en lugar de llamar a SetText directamente.

@Stecy: Aquí está nuestro código centralizado:

La clase StaHelper simplemente ejecuta un código arbitrario en un hilo en el Single Thread Apartment (STA), requerido por el portapapeles.

abstract class StaHelper
{
    readonly ManualResetEvent _complete = new ManualResetEvent( false );    

    public void Go()
    {
        var thread = new Thread( new ThreadStart( DoWork ) )
        {
            IsBackground = true,
        }
        thread.SetApartmentState( ApartmentState.STA );
        thread.Start();
    }

    // Thread entry method
    private void DoWork()
    {
        try
        {
            _complete.Reset();
            Work();
        }
        catch( Exception ex )
        {
            if( DontRetryWorkOnFailed )
                throw;
            else
            {
                try
                {
                    Thread.Sleep( 1000 );
                    Work();
                }
                catch
                {
                    // ex from first exception
                    LogAndShowMessage( ex );
                }
            }
        }
        finally
        {
            _complete.Set();
        }
    }

    public bool DontRetryWorkOnFailed{ get; set; }

    // Implemented in base class to do actual work.
    protected abstract void Work();
}

Luego tenemos una clase específica para configurar texto en el portapapeles. La creación de un DataObject manualmente es necesaria en algunos casos DataObject en algunas versiones de Windows / .NET. No recuerdo los escenarios exactos ahora y puede que no sea necesario en .NET 3.5.

class SetClipboardHelper : StaHelper
{
    readonly string _format;
    readonly object _data;

    public SetClipboardHelper( string format, object data )
    {
        _format = format;
        _data = data;
    }

    protected override void Work()
    {
        var obj = new System.Windows.Forms.DataObject(
            _format,
            _data
        );

        Clipboard.SetDataObject( obj, true );
    }
}

El uso se ve así:

new SetClipboardHelper( DataFormats.Text, "See, I'm on the clipboard" ).Go();

Si tengo texto en una cadena, ¿cómo puedo copiarlo en el portapapeles para que el usuario pueda pegarlo en otra ventana (por ejemplo, de mi aplicación al Bloc de notas)?


En Windows Forms, si su cadena está en un cuadro de texto, puede usar esto fácilmente:

textBoxcsharp.SelectAll();
textBoxcsharp.Copy();
textBoxcsharp.DeselectAll();

Usando la solución mostrada en esta pregunta, System.Windows.Forms.Clipboard.SetText(...) , produce la excepción:

El subproceso actual debe establecerse en el modo de apartamento de un solo subproceso (STA) antes de que se puedan realizar llamadas OLE

Para evitar esto, puede agregar el atributo:

[STAThread]

a

static void Main(string[] args)

Utilice try - catch , incluso si tiene un error, todavía se copiará.

Try
   Clipboard.SetText("copy me to clipboard")
Catch ex As Exception

End Try

Si usa un cuadro de mensaje para capturar la excepción, le mostrará un error, pero el valor aún se copia en el portapapeles.







clipboard