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

Resuelto Elie asked hace 15 años • 8 respuestas

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

Elie avatar May 23 '09 01:05 Elie
Aceptado

Puedes usar System.Windows.Forms.Clipboard.SetText(...).

ravuya avatar May 22 '2009 18:05 ravuya

System.Windows.Forms.Clipboard.SetText(Formularios de Windows) o System.Windows.Clipboard.SetText(WPF)

Jeff Moser avatar May 22 '2009 18:05 Jeff Moser

Ojalá llamar SetTextfuera así de fácil, pero hay bastantes problemas con los que tienes que lidiar. Debe asegurarse de que el hilo al que lo está llamando se esté ejecutando en STA. A veces puede fallar con un error de acceso denegado y luego funcionar segundos después sin problemas, algo que tiene que ver con los problemas de sincronización COM en el portapapeles. Y si se accede a su aplicación a través de Escritorio remoto, el acceso al portapapeles es incompleto. Usamos un método centralizado para manejar todos estos escenarios en lugar de llamar SetTextdirectamente.

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

La clase StaHelper simplemente ejecuta algún código arbitrario en un subproceso 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. DataObjectEs necesario crear un archivo manualmente en algunos casos extremos en algunas versiones de Windows/.NET. No recuerdo los escenarios exactos ahora y es posible 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();
Paul Alexander avatar May 22 '2009 19:05 Paul Alexander

WPF: System.Windows.Clipboard(PresentaciónCore.dll)

Formas de Win:System.Windows.Forms.Clipboard

Ambos tienen un SetTextmétodo estático.

bsneeze avatar May 22 '2009 18:05 bsneeze

Esto funciona para mí:

Quieres hacer:

System.Windows.Forms.Clipboard.SetText("String to be copied to Clipboard");

Pero provoca un error que indica que debe estar en un único hilo de ApartmentState.STA.

Así que hagamos que se ejecute en ese hilo. El código para ello:

public void somethingToRunInThread()
{
    System.Windows.Forms.Clipboard.SetText("String to be copied to Clipboard");
}

protected void copy_to_clipboard()
{
    Thread clipboardThread = new Thread(somethingToRunInThread);
    clipboardThread.SetApartmentState(ApartmentState.STA);
    clipboardThread.IsBackground = false;
    clipboardThread.Start();
}

Después de llamar copy_to_clipboard(), la cadena se copia en el portapapeles, por lo que puede Pegar o Ctrl+ Vy recuperar la cadena como Cadena para copiarla en el portapapeles .

benli1212 avatar Dec 20 '2012 17:12 benli1212