如何将字符串的内容复制到C#中的剪贴板?

Eli*_*lie 257 .net c# clipboard

如果我在String中有一些文本,我如何将其复制到剪贴板,以便用户可以将其粘贴到另一个窗口(例如,从我的应用程序到记事本)?

rav*_*uya 329

你可以用System.Windows.Forms.Clipboard.SetText(...).

  • 这适用于WinForms; 对于WPF,请参阅Jeff Moser的回答(目前为2). (11认同)
  • 对于控制台应用程序,您需要使用[STAThread]属性修饰Main (4认同)
  • @DannyBeckett现在只有_1_下来. (2认同)

Jef*_*ser 138

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

  • 如果是控制台应用程序怎么办? (16认同)
  • 您仍然可以使用其中之一,您只需将winforms dll添加为参考程序集. (16认同)

Pau*_*der 64

我希望打电话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();
}
Run Code Online (Sandbox Code Playgroud)

然后我们有一个特定的类来设置剪贴板上的文本.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 );
    }
}
Run Code Online (Sandbox Code Playgroud)

用法如下:

new SetClipboardHelper( DataFormats.Text, "See, I'm on the clipboard" ).Go();
Run Code Online (Sandbox Code Playgroud)

  • +1,我至少经历过其中一些陷阱.如果我在try {...} catch(System.Runtime.InteropServices.ExternalException){}中包装剪贴板访问,它对我来说很好. (4认同)
  • 这个答案应该得到比它更多的支持.此外,您应该提出一个自我回答的问题,例如"如何在非STA上下文中运行STA代码" (3认同)
  • 我在这里,一年半之后,从16/2/19起几乎没有这个问题的记忆,再次复制了这个课程。 (2认同)

bsn*_*eze 22

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

的WinForms: System.Windows.Forms.Clipboard

两者都有静态SetText方法.


小智 16

这对我有用:

你想做:

System.Windows.Forms.Clipboard.SetText("String to be copied to Clipboard");
Run Code Online (Sandbox Code Playgroud)

但它会导致错误,说它必须在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();
}
Run Code Online (Sandbox Code Playgroud)

调用之后copy_to_clipboard(),字符串被复制到剪贴板中,因此您可以粘贴或Ctrl+ V并将字符串作为String返回以复制到剪贴板.


小智 14

使用此问题中显示的解决方案System.Windows.Forms.Clipboard.SetText(...),导致异常:

在进行OLE调用之前,必须将当前线程设置为单线程单元(STA)模式

要防止这种情况,您可以添加以下属性:

[STAThread]
Run Code Online (Sandbox Code Playgroud)

static void Main(string[] args)
Run Code Online (Sandbox Code Playgroud)


Mag*_*dud 7

在Windows窗体中,如果您的字符串位于文本框中,则可以轻松使用:

textBoxcsharp.SelectAll();
textBoxcsharp.Copy();
textBoxcsharp.DeselectAll();
Run Code Online (Sandbox Code Playgroud)

  • 您无需放入所有选择和选择的垃圾。只需将其输入:`textBox1.Copy();` (2认同)
  • 实际上,您确实需要SelectAll()和DeselectAll()垃圾。根据https://msdn.microsoft.com/zh-cn/library/system.windows.forms.textboxbase.copy(v=vs.120).aspx,复制到剪贴板的内容是“当前选择的”文本。 (2认同)
  • 你需要把SelectAll(),否则它不起作用,我只是[尝试在这个无用的应用程序](https://github.com/Magneticdud/Paginatore/commit/5b58a89bf947c1be345861e2adbadf3270ad88f7).但是,不需要在WPF应用程序中使用DeselectAll(). (2认同)