【问题标题】:How do I copy the contents of a String to the clipboard in C#? [duplicate]如何将字符串的内容复制到 C# 中的剪贴板? [复制]
【发布时间】:2010-10-28 07:31:33
【问题描述】:

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

【问题讨论】:

标签: c# .net clipboard


【解决方案1】:

【讨论】:

  • 如果是控制台应用程序呢?
  • 你仍然可以使用任何一个,你只需将 winforms dll 添加为参考程序集。
  • @Cheeso 用于控制台应用程序 se 回答 below
  • WPF 方法在 .Net 4.6.1 控制台应用程序中对我不起作用,Winforms 方法在我将 [STAThread] 属性添加到 Main() 后完美运行
【解决方案2】:

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

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

为了防止这种情况,你可以添加属性:

[STAThread]

static void Main(string[] args)

【讨论】:

    【解决方案3】:

    这对我有用:

    你想做的:

    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的形式取回字符串被复制到剪贴板

    【讨论】:

    • 正确的钱。谢谢!
    【解决方案4】:

    使用try-catch,即使有错误仍然会复制。

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

    如果您使用消息框捕获异常,它会显示错误,但该值仍会复制到剪贴板。

    【讨论】:

    • 你确定吗?您是否尝试过多次,例如10倍?也许你只是幸运?一般情况下不需要重试(作为一种解决方法)吗?
    【解决方案5】:

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

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

    【讨论】:

    • 你不需要放入所有的选择和删除垃圾。只需简单地输入:textBox1.Copy();
    • 实际上,您确实需要 SelectAll() 和 DeselectAll() 垃圾。根据msdn.microsoft.com/en-us/library/…,复制到剪贴板的是当前选择的文本。
    • 你需要把SelectAll(),否则不行,我就tried in this useless app。不过,在 WPF 应用程序中无需使用 DeselectAll()。
    • 我喜欢这个,因为它使您不必将 STA 属性添加到您的类。我只是在一些调试过程中想要这个,我并没有改变我的代码的其他部分只是为了得到一些东西到键盘缓冲区。
    【解决方案6】:

    我希望致电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();
    }
    

    然后我们有一个用于在剪贴板上设置文本的特定类。在某些 Windows/.NET 版本的某些边缘情况下,需要手动创建 DataObject。我现在不记得确切的场景了,在 .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();
    

    【讨论】:

    • +1,我至少经历过其中一些陷阱。如果我将剪贴板访问包装在 try { ...} catch (System.Runtime.InteropServices.ExternalException) { } 中,这对我来说没问题。
    • @Paul,您能解释一下您的集中式方法吗?
    • 这个答案应该得到比它更多的支持。此外,您应该提出一个自我回答的问题,例如“如何在非 STA 上下文中运行 STA 代码”
    • 我在这里,一年半后,几乎没有记忆从 2/19/16 开始,再次复制这堂课。
    • 什么是数据格式?
    【解决方案7】:

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

    Winforms:System.Windows.Forms.Clipboard

    两者都有一个静态的SetText 方法。

    【讨论】:

    • 感谢您包含 PresentationCore.dll 参考。默认情况下不包含在控制台应用程序中
    【解决方案8】:

    您可以使用System.Windows.Forms.Clipboard.SetText(...)

    【讨论】:

    • 这是针对 WinForms 的;对于 WPF,请参阅 Jeff Moser 的回答(目前为 2)。
    • @DannyBeckett 现在只有 1 了。
    • 对于控制台应用程序,您需要使用属性 [STAThread] 装饰 Main
    • 问题是“一些文本”,但为了稳健性:if the string is empty 会发生什么?
    猜你喜欢
    • 1970-01-01
    • 2010-11-18
    • 2013-11-21
    • 2010-10-09
    • 2019-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多