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

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


person Elie    schedule 22.05.2009    source источник
comment
без winforms или wpf: stackoverflow.com/a/13571530/359135   -  person    schedule 12.10.2013


Ответы (8)


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

person ravuya    schedule 22.05.2009
comment
Это для WinForms; для WPF см. ответ Джеффа Мозера (в настоящее время 2 вниз). - person Danny Beckett; 25.10.2013
comment
@DannyBeckett Сейчас только 1 вниз. - person Anonymous Pi; 26.03.2014
comment
Для консольных приложений вам необходимо украсить основную часть атрибутом [STAThread]. - person John Henckel; 01.07.2015
comment
В вопросе содержится текст, но для надежности: что происходит , если строка пуста? - person Peter Mortensen; 15.01.2017

System.Windows.Forms.Clipboard.SetText (Windows Forms) или _ 2_ (WPF)

person Jeff Moser    schedule 22.05.2009
comment
Что, если это консольное приложение? - person Cheeso; 22.05.2009
comment
Вы по-прежнему можете использовать любой из них, вам просто нужно добавить DLL winforms в качестве эталонной сборки. - person Jeff Moser; 22.05.2009
comment
@Cheeso для консольного приложения см. ниже - person xtreampb; 01.11.2016
comment
Метод WPF не работал у меня в консольном приложении .Net 4.6.1, метод Winforms отлично работал после того, как я добавил свойство [STAThread] в Main () - person AceJordin; 26.01.2019

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

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

Класс StaHelper просто выполняет некоторый произвольный код в потоке в однопоточной квартире (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();
person Paul Alexander    schedule 22.05.2009
comment
+1, я испытал по крайней мере некоторые из этих ошибок. У меня все получилось, если я оберну доступ к буферу обмена в try {...} catch (System.Runtime.InteropServices.ExternalException) {}. - person Joe; 22.05.2009
comment
@ Пол, не могли бы вы объяснить свой централизованный метод? - person Stécy; 27.01.2010
comment
Этот ответ заслуживает гораздо большего количества голосов, чем он имеет. Кроме того, вы должны задать себе вопрос, например, как запустить код STA в контексте, отличном от STA. - person Sidney; 20.02.2016
comment
Вот я, полтора года спустя, почти не помня об этой проблеме от 19.02.16, снова копирую этот класс. - person Sidney; 16.10.2017
comment
Что такое DataFormats? - person Kiquenet; 08.04.2019
comment
Я закрыл это как дубликат stackoverflow.com/questions/3546016/. Подумайте о переносе своего ответа туда (и посмотрите, можете ли вы одновременно модернизировать его для _1 _ / _ 2 _ / _ 3_, если хотите). - person Alexei Levenkov; 03.12.2019

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

Winforms: System.Windows.Forms.Clipboard

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

person bsneeze    schedule 22.05.2009
comment
Спасибо за ссылку на PresentationCore.dll. По умолчанию не входит в консольное приложение - person xtreampb; 01.11.2016

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

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

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 и вернуть строку как String для копирования в буфер обмена .

person benli1212    schedule 20.12.2012
comment
Право на деньги. Спасибо! - person CodeBreaker; 19.07.2016

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

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

Чтобы этого не произошло, можно добавить атрибут:

[STAThread]

to

static void Main(string[] args)
person Leroy    schedule 02.05.2012

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

textBoxcsharp.SelectAll();
textBoxcsharp.Copy();
textBoxcsharp.DeselectAll();
person Magnetic_dud    schedule 11.09.2009
comment
вам не нужно помещать весь мусор для выбора и удаления. Просто введите это: textBox1.Copy(); - person Dozer789; 16.02.2014
comment
На самом деле вам нужен мусор SelectAll () и DeselectAll (). Согласно msdn .microsoft.com / en-us / library / то, что копируется в буфер обмена, является текущим выбранным текстом. - person G. Stewart; 12.04.2016
comment
вам нужно поставить SelectAll (), иначе это не сработает, я просто попробовал в этом бесполезном приложении. Однако нет необходимости использовать DeselectAll () в приложениях WPF. - person Magnetic_dud; 13.04.2016
comment
Мне это нравится, потому что это избавляет вас от необходимости добавлять атрибуты STA к вашему классу. Я просто хотел этого во время некоторой отладки, и я не менял другие части моего кода, просто чтобы что-то передать в буфер клавиатуры. - person MattSlay; 15.04.2019

Используйте _1 _-_ 2_, даже если у него есть ошибка, он все равно скопирует.

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

End Try

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

person Abu Faisal    schedule 18.09.2015
comment
Вы уверены, что? Вы пробовали это несколько раз, например 10 раз? Может, вам просто повезло? Не требуется ли вообще повторная попытка (в качестве обходного пути)? - person Peter Mortensen; 17.03.2019