gpt4 book ai didi

c# - .Net Core - 复制到剪贴板?

转载 作者:IT王子 更新时间:2023-10-29 04:46:52 25 4
gpt4 key购买 nike

是否可以使用 .Net Core (以与平台无关的方式) 将内容复制到剪贴板?

似乎Clipboard类丢失,P/Invoking 不是 Windows 之外的选项。

<子>编辑:不幸的是,直到现在我的问题和人们在阅读问题时听到的内容之间存在差异。根据评论和答案,有两件事很清楚。首先,很少有人关心是否存在最真实的“象牙塔”平台不可知论。其次,当人们发布代码示例来展示您如何在不同平台上使用剪贴板时,技术上正确的答案(“no, it's not possible”)令人困惑。所以我划掉了附加条款。

最佳答案

我的这个项目 (https://github.com/SimonCropp/TextCopy) 使用了 PInvoke 和命令行调用的混合方法。目前支持

  • 装有 .NET Framework 4.6.1 及更高版本的 Windows
  • 使用 .NET Core 2.0 及更高版本的 Windows
  • 装有 Mono 5.0 及更高版本的 Windows
  • 带有 .NET Core 2.0 及更高版本的 OSX
  • 带有 Mono 5.20.1 及更高版本的 OSX
  • 带有 .NET Core 2.0 及更高版本的 Linux
  • 装有 Mono 5.20.1 及更高版本的 Linux

用法:

Install-Package TextCopy

TextCopy.ClipboardService.SetText("Text to place in clipboard");

或者直接使用实际代码

window

https://github.com/CopyText/TextCopy/blob/master/src/TextCopy/WindowsClipboard.cs

static class WindowsClipboard
{
public static void SetText(string text)
{
OpenClipboard();

EmptyClipboard();
IntPtr hGlobal = default;
try
{
var bytes = (text.Length + 1) * 2;
hGlobal = Marshal.AllocHGlobal(bytes);

if (hGlobal == default)
{
ThrowWin32();
}

var target = GlobalLock(hGlobal);

if (target == default)
{
ThrowWin32();
}

try
{
Marshal.Copy(text.ToCharArray(), 0, target, text.Length);
}
finally
{
GlobalUnlock(target);
}

if (SetClipboardData(cfUnicodeText, hGlobal) == default)
{
ThrowWin32();
}

hGlobal = default;
}
finally
{
if (hGlobal != default)
{
Marshal.FreeHGlobal(hGlobal);
}

CloseClipboard();
}
}

public static void OpenClipboard()
{
var num = 10;
while (true)
{
if (OpenClipboard(default))
{
break;
}

if (--num == 0)
{
ThrowWin32();
}

Thread.Sleep(100);
}
}

const uint cfUnicodeText = 13;

static void ThrowWin32()
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}

[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr GlobalLock(IntPtr hMem);

[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GlobalUnlock(IntPtr hMem);

[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool OpenClipboard(IntPtr hWndNewOwner);

[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool CloseClipboard();

[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr SetClipboardData(uint uFormat, IntPtr data);

[DllImport("user32.dll")]
static extern bool EmptyClipboard();
}

苹果操作系统

https://github.com/CopyText/TextCopy/blob/master/src/TextCopy/OsxClipboard.cs

static class OsxClipboard
{
public static void SetText(string text)
{
var nsString = objc_getClass("NSString");
IntPtr str = default;
IntPtr dataType = default;
try
{
str = objc_msgSend(objc_msgSend(nsString, sel_registerName("alloc")), sel_registerName("initWithUTF8String:"), text);
dataType = objc_msgSend(objc_msgSend(nsString, sel_registerName("alloc")), sel_registerName("initWithUTF8String:"), NSPasteboardTypeString);

var nsPasteboard = objc_getClass("NSPasteboard");
var generalPasteboard = objc_msgSend(nsPasteboard, sel_registerName("generalPasteboard"));

objc_msgSend(generalPasteboard, sel_registerName("clearContents"));
objc_msgSend(generalPasteboard, sel_registerName("setString:forType:"), str, dataType);
}
finally
{
if (str != default)
{
objc_msgSend(str, sel_registerName("release"));
}

if (dataType != default)
{
objc_msgSend(dataType, sel_registerName("release"));
}
}
}

[DllImport("/System/Library/Frameworks/AppKit.framework/AppKit")]
static extern IntPtr objc_getClass(string className);

[DllImport("/System/Library/Frameworks/AppKit.framework/AppKit")]
static extern IntPtr objc_msgSend(IntPtr receiver, IntPtr selector);

[DllImport("/System/Library/Frameworks/AppKit.framework/AppKit")]
static extern IntPtr objc_msgSend(IntPtr receiver, IntPtr selector, string arg1);

[DllImport("/System/Library/Frameworks/AppKit.framework/AppKit")]
static extern IntPtr objc_msgSend(IntPtr receiver, IntPtr selector, IntPtr arg1, IntPtr arg2);

[DllImport("/System/Library/Frameworks/AppKit.framework/AppKit")]
static extern IntPtr sel_registerName(string selectorName);

const string NSPasteboardTypeString = "public.utf8-plain-text";
}

Linux

https://github.com/CopyText/TextCopy/blob/master/src/TextCopy/LinuxClipboard_2.1.cs

static class LinuxClipboard
{
public static void SetText(string text)
{
var tempFileName = Path.GetTempFileName();
File.WriteAllText(tempFileName, text);
try
{
BashRunner.Run($"cat {tempFileName} | xclip");
}
finally
{
File.Delete(tempFileName);
}
}

public static string GetText()
{
var tempFileName = Path.GetTempFileName();
try
{
BashRunner.Run($"xclip -o > {tempFileName}");
return File.ReadAllText(tempFileName);
}
finally
{
File.Delete(tempFileName);
}
}
}

static class BashRunner
{
public static string Run(string commandLine)
{
var errorBuilder = new StringBuilder();
var outputBuilder = new StringBuilder();
var arguments = $"-c \"{commandLine}\"";
using (var process = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = "bash",
Arguments = arguments,
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = false,
}
})
{
process.Start();
process.OutputDataReceived += (sender, args) => { outputBuilder.AppendLine(args.Data); };
process.BeginOutputReadLine();
process.ErrorDataReceived += (sender, args) => { errorBuilder.AppendLine(args.Data); };
process.BeginErrorReadLine();
if (!process.WaitForExit(500))
{
var timeoutError = $@"Process timed out. Command line: bash {arguments}.
Output: {outputBuilder}
Error: {errorBuilder}";
throw new Exception(timeoutError);
}
if (process.ExitCode == 0)
{
return outputBuilder.ToString();
}

var error = $@"Could not execute process. Command line: bash {arguments}.
Output: {outputBuilder}
Error: {errorBuilder}";
throw new Exception(error);
}
}
}

关于c# - .Net Core - 复制到剪贴板?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44205260/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com