如何在C#中将数据复制到剪贴板

561

我该如何在C#中将字符串(例如“hello”)复制到系统剪贴板,这样下次按CTRL+V就可以获得“hello”呢?


8
可能是如何在C#中将字符串内容复制到剪贴板?的重复问题。 - Ondrej Janacek
10个回答

967

有两个类存在于不同的程序集和命名空间中。

  • WinForms:使用以下命名空间声明,确保 Main 标记为带有 [STAThread] 属性:

    using System.Windows.Forms;
    
  • WPF: 使用以下命名空间声明

  • using System.Windows;
    
  • 控制台:添加对System.Windows.Forms的引用,使用以下命名空间声明,确保将 Main 标记为带有[STAThread]属性。另一个答案中提供了逐步指南。

  • using System.Windows.Forms;
    

要复制完全相同的字符串(在这种情况下是字面量):

Clipboard.SetText("Hello, clipboard");

要复制文本框的内容,请使用TextBox.Copy()或先获取文本,然后设置剪贴板值:

Clipboard.SetText(txtClipboard.Text);

点击此处查看示例。 或者... 官方MSDN文档 或者 这里的WPF


备注:


@KierenJohnstone 通过键值对访问剪贴板内容是否可行? - Honinbo Shusaku
@Abdul - 我不确定你的意思。剪贴板内容可以是文本、文件、图像或任何自定义数据。kv-对的概念似乎与剪贴板没有任何关系? - Kieren Johnstone
@KierenJohnstone,我正在尝试制作的是一个用户可以将多个内容存储在剪贴板中的工具。这些内容将通过密钥进行访问。它类似于HTML5本地存储。但是,由于剪贴板的性质,这样的操作是否可能? - Honinbo Shusaku
如果在ASP.NET中遇到错误,请尝试使用新线程: var thread = new Thread(param => { Clipboard.SetText(txtName.Text); }); thread.SetApartmentState(ApartmentState.STA); thread.Start(); - user3790692
2
skia.heliou的回答帮了我:在添加[STAThreadAttribute]属性后,我的Clipboard.SetText方法开始工作了。 - viteo
显示剩余3条评论

60

为了以逐步方式创建控制台项目,您首先需要添加System.Windows.Forms引用。以下步骤适用于使用.NET 4.5的Visual Studio Community 2013:

  1. Solution Explorer中展开控制台项目。
  2. 右键单击References,然后点击Add Reference...
  3. Assemblies组下的Framework中,选择System.Windows.Forms
  4. 单击OK

接下来,在代码顶部与其他using语句一起添加以下语句:

using System.Windows.Forms;

然后,将以下任一ClipboardSetText语句添加到您的代码中:

Clipboard.SetText("hello");
// OR
Clipboard.SetText(helloString);
最后,将 Main 方法添加 STAThreadAttribute,以避免出现 System.Threading.ThreadStateException
[STAThreadAttribute]
static void Main(string[] args)
{
  // ...
}

1
在.NET Framework系统类库中,StackOverflowException类紧随STAThreadAttribute之后。=) - nikodaemus

50

使用 WPF C# 复制到剪贴板时遇到 System.Threading.ThreadStateException,以下是我的经验,并附上了可以在所有浏览器中正常工作的代码:

Thread thread = new Thread(() => Clipboard.SetText("String to be copied to clipboard"));
thread.SetApartmentState(ApartmentState.STA); //Set the thread to STA
thread.Start(); 
thread.Join();

感谢这里的帖子提供的帮助。

但是这只在本地主机上有效,所以不要在服务器上尝试,因为它不会起作用。

在服务器端,我使用了zeroclipboard来实现。这是经过大量研究找到的唯一方法。


我在自动化Selenium测试(webdriver)中使用它,效果非常好! - andrew.fox
@andrew.fox 你在你的服务器-客户端模型上尝试过吗?因为如果是两台独立的机器,我猜它不应该工作。 - BMaximus
不,Selenium 在代理机器上打开浏览器窗口。 - andrew.fox
使用此方法,当您在使用具有多个线程的控制台应用程序时,无需使用[STAThreadAttribute]。 - Donovan Phoenix

43
Clipboard.SetText("hello");

你需要使用 System.Windows.Forms 或者 System.Windows 命名空间。


9

Clip.exe是Windows中用于设置剪贴板的可执行文件。注意,它不适用于除Windows以外的其他操作系统,这仍然很糟糕。

        /// <summary>
        /// Sets clipboard to value.
        /// </summary>
        /// <param name="value">String to set the clipboard to.</param>
        public static void SetClipboard(string value)
        {
            if (value == null)
                throw new ArgumentNullException("Attempt to set clipboard with null");

            Process clipboardExecutable = new Process(); 
            clipboardExecutable.StartInfo = new ProcessStartInfo // Creates the process
            {
                RedirectStandardInput = true,
                FileName = @"clip", 
            };
            clipboardExecutable.Start();

            clipboardExecutable.StandardInput.Write(value); // CLIP uses STDIN as input.
            // When we are done writing all the string, close it so clip doesn't wait and get stuck
            clipboardExecutable.StandardInput.Close(); 

            return;
        }

在我加入UseShellExecute = falseProcessStartInfo中后,这个方法对我起作用了,就像文档https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.processstartinfo.redirectstandardinput?view=net-7.0#remarks中所写的那样。 - undefined
此外,如果需要更多的ASCII支持,请将ProcessStartInfo.StandardInputEncoding设置为System.Text.Encoding Unicode。除非您使用较旧的.NET版本,否则请在Process.StandardInput.BaseStream周围创建自己的StreamWriter,并使用WriteClose ,请参阅:https://stackoverflow.com/a/50001438/1997873。 - undefined

2
如果您不想将线程设置为STAThread,请使用Clipboard.SetDataObject(object sthhere)
Clipboard.SetDataObject("Yay! No more STA thread!");

1
你的回答可以通过提供更多支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心中找到有关如何编写良好答案的更多信息。 - Community
它可以工作,但没有STAThread就不行。我的C# WinForms程序默认在Main()(在Program.cs中)上有STAThread。所以这可能只是旧版本VS和VS2019之间的差异。从Main()中删除STAThread会导致尝试复制时出现异常。 - MichaelS
我在没有 STAThread 的情况下也会遇到异常,剪贴板将被清空(而不是其中包含该字符串)。答案似乎是不正确的,而不是支持得不好。 - Anders Lindén

2

这适用于 .net core,无需引用 System.Windows.Forms

using Windows.ApplicationModel.DataTransfer;

DataPackage package = new DataPackage();
package.SetText("text to copy");
Clipboard.SetContent(package);

它支持跨平台。在Windows上,您可以按下windows + V查看剪贴板历史记录。


1
在ASP.net Web Forms中,如果在@page中使用AspCompat="true",则需要将system.windows.forms添加到您的项目中。在您的web.config文件中添加以下内容:
  <appSettings>
    <add key="aspnet:UseTaskFriendlySynchronizationContext" value="false" />
  </appSettings>

然后你可以使用:

Clipboard.SetText(CreateDescription());

0

0
对于现代跨平台的.NET,您需要使用MAUI版本。简单来说,您可以使用await Clipboard.Default.SetTextAsync("This text was highlighted in the UI.");,并且应该引用Microsoft.Maui.Essentials.dll。详细的解答在this article中有详细介绍。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接