Как мне скопировать содержимое строки в буфер обмена в C#?

Если у меня есть какой-то текст в строке, как я могу скопировать его в буфер обмена, чтобы пользователь мог вставить его в другое окно (например, из моего приложения в блокнот)?

8 ответов

Решение

Ты можешь использовать System.Windows.Forms.Clipboard.SetText(...),

System.Windows.Forms.Clipboard.SetText (Winforms) или System.Windows.Clipboard.SetText (WPF)

Я желаю звонить SetText Было бы так просто, но есть немало ошибок, с которыми вам приходится иметь дело. Вы должны убедиться, что поток, к которому вы его вызываете, работает в STA. Иногда он может завершиться с ошибкой отказа в доступе, а затем работать без проблем через несколько секунд - что-то связанное с проблемами синхронизации COM в буфере обмена. И если к вашему приложению обращаются через удаленный рабочий стол, доступ к буферу обмена оказывается поверхностным. Мы используем централизованный метод для обработки всех этих сценариев вместо вызова SetText непосредственно.

@ Stecy: Вот наш централизованный код:

Класс StaHelper просто выполняет некоторый произвольный код в потоке в Single Thread Apartment (STA) - необходимый для буфера обмена.

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

Тогда у нас есть специальный класс для установки текста в буфер обмена. Создание DataObject вручную требуется в некоторых крайних случаях в некоторых версиях Windows/.NET. Я не помню точных сценариев сейчас, и это может не потребоваться в.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 );
    }
}

Использование выглядит так:

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

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

Winforms: System.Windows.Forms.Clipboard

У обоих есть статика SetText метод.

Это работает для меня:

Ты хочешь сделать:

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

Но это вызывает ошибку, говорящую, что это должно быть в единственном потоке ApartmentState.STA.

Итак, давайте запустим его в такой ветке. Код для этого:

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

После звонка copy_to_clipboard()строка копируется в буфер обмена, поэтому вы можете вставить или Ctrl + V и вернуть строку как строку для копирования в буфер обмена.

Используя решение, показанное в этом вопросе, System.Windows.Forms.Clipboard.SetText(...), приводит к исключению:

Текущий поток должен быть установлен в однопотоковый режим (STA), прежде чем можно будет выполнять вызовы OLE

Чтобы предотвратить это, вы можете добавить атрибут:

[STAThread]

в

static void Main(string[] args)

В Windows Forms, если ваша строка находится в текстовом поле, вы можете легко использовать это:

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

Clipboard.SetText это то, что вы хотите.

Использование try-catch, даже если он имеет ошибку, он все равно будет копировать.

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

End Try

Если вы используете окно сообщения для захвата исключения, оно покажет вам ошибку, но значение все равно будет скопировано в буфер обмена.

Другие вопросы по тегам