【问题标题】:Copy result to clipboard将结果复制到剪贴板
【发布时间】:2014-07-11 21:28:01
【问题描述】:

大家好,我编写了一个控制台应用程序:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
using System.Text.RegularExpressions;

namespace ConsoleApplication1
{
    class Program
    {
        public static void Main(String[] args)
        {
            if (args.Length == 0)
            {
                Console.WriteLine("No file to upload...");
                Environment.Exit(0);
            }
            else
                Console.WriteLine("[~] Trying to upload: " + args[0]);
            string name = Regex.Match(args[0], @"[^\\]*$").Value;
            ftp ftpClient = new ftp(@"ftp://site.ru/", "dfgd", "QWERTY_123");
            ftpClient.upload("www/site.ru/upload/" + name, args[0]);
            Console.WriteLine("[+] Upload File Complete");
            Console.ReadKey();
        }
    }
}

Console.WriteLine("[+] Upload File Complete"); 后如何将args[0] 复制到剪贴板?

【问题讨论】:

  • 一种可能的解决方案是使用System.Windows.Forms 中的Clipboard 类,您需要引用它。
  • 更新了答案以避免引用 System.Windows.Forms

标签: c#


【解决方案1】:

首先,您必须在应用程序中添加对 System.Windows.Forms 的引用。

转到项目 -> 添加引用,从刚刚打开的窗口中的 .NET 选项卡中选择 System.Windows.Forms。

您必须通过将 STAThread 属性应用于 Main() 函数来避免 ThreadStateException。然后您就可以毫无问题地使用剪贴板功能了。

using System;
using System.Windows.Forms;

class Program 
{
    [STAThread]
    static void Main(string[] args) 
    {
         Clipboard.SetText("this is in clipboard now");
    }
}

如果您不想使用对 System.Windows.Forms 的引用,您可以通过 P/Invoke

来实现

平台调用剪贴板 API 是一种可能的解决方案。示例:

using System.Runtime.InteropServices;
class Program
{
    [DllImport("user32.dll")]
    internal static extern bool OpenClipboard(IntPtr hWndNewOwner);

    [DllImport("user32.dll")]
    internal static extern bool CloseClipboard();

    [DllImport("user32.dll")]
    internal static extern bool SetClipboardData(uint uFormat, IntPtr data);

    [STAThread]
    static void Main(string[] args)
    {
        OpenClipboard(IntPtr.Zero);
        var yourString = "Hello World!";
        var ptr = Marshal.StringToHGlobalUni(yourString);
        SetClipboardData(13, ptr);
        CloseClipboard();
        Marshal.FreeHGlobal(ptr);
    }
}

这只是一个例子。在代码周围添加一些错误处理,例如检查 P/Invoke 函数的返回值将是一个很好的补充。

SetClipboardData 很有趣,您还需要确保打开和关闭剪贴板。

作为第一个参数传入的13 是数据格式。 13means unicode string.

【讨论】:

  • 我在 MSDN 上读到“如果 SetClipboardData 成功,则系统拥有由 hMem 参数标识的对象。应用程序可能不会写入或释放数据”。但是根据these commentsMarshal.StringToHGlobalUni是不合适的,看下面的另一个answer
【解决方案2】:

Marshal.StringToHGlobalUni 函数实际上以不适合 SetClipboardData 的方式分配内存(使用带有 LMEM_FIXED 的 LocalAlloc),这可能会导致崩溃。 (你不会期望它给出方法名称,但进入代码,例如使用 ReSharper 会揭示这一点。)根据文档,SetClipboardData 需要带有 GMEM_MOVABLE 的 GlobalAlloc:SetClipboardData on MSDN

这是 MIT 许可的 System.Windows.Forms 替代方案,经过测试并完成错误处理:Clippy

(剪贴板推送代码本身可以在这里找到:Clippy.cs

【讨论】:

    【解决方案3】:

    你需要使用ClipBoard.SetText方法

     Clipboard.SetText(args[0], TextDataFormat.Text);
    

    【讨论】:

      猜你喜欢
      • 2016-11-23
      • 1970-01-01
      • 1970-01-01
      • 2018-04-14
      • 1970-01-01
      • 1970-01-01
      • 2017-05-15
      • 1970-01-01
      • 2020-02-06
      相关资源
      最近更新 更多