tags:

views:

1540

answers:

6

If I have some text in a String, how can I copy that to the clipboard so that the user can paste it into another window (e.g. from my application to Notepad)?

+4  A: 

WPF: System.Windows.Clipboard (PresentationCore.dll)

Winforms: System.Windows.Forms.Clipboard

Both have a static SetText method.

pyrochild
+7  A: 

System.Windows.Forms.Clipboard.SetText (Winforms) or System.Windows.Clipboard.SetText (WPF)

Jeff Moser
What if it is a Console app?
Cheeso
You can still use either, you'd just add the winforms dll as a reference assembly.
Jeff Moser
+2  A: 

Clipboard.SetText is what you want

http://msdn.microsoft.com/en-us/library/ydby206k.aspx

Bob
+12  A: 

You can use System.Windows.Forms.Clipboard.SetText(...)

ravuya
+4  A: 

I wish calling SetText were that easy but there are quite a few gotchas that you have to deal with. You have to make sure that the thread you are calling it on is running in the STA. It can sometimes fail with an access denied error then work seconds later without problem - something to do with the COM timing issues in the clipboard. And if your application is accessed over Remote Desktop access to the clipboard is sketchy. We use a centralized method to handle all theses scenarios instead of calling SetText directly.

@Stecy: Here's our centralized code:

The StaHelper class simply executes some arbitrary code on a thread in the Single Thread Apartment (STA) - required by the clipboard.

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

Then we have a specific class for setting text on the clipboard. Creating a DataObject manually is required in some edge cases on some versions of Windows/.NET. I don't recall the exact scenarios now and it may not be required in .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 );
    }
}

Usage looks like this:

new SetClipboardHelper( DataFormats.Text, "See, I'm on the clipboard" ).Go();
Paul Alexander
+1, I've experienced at least some of these gotchas. It's worked OK for me if I wrap the clipboard access in try { ...} catch (System.Runtime.InteropServices.ExternalException) { }.
Joe
@Paul, would you be so kind to explain your centralized method?
Stecy
A: 

If your string is in a textbox, you can easily use this:

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