我正在编写一个自动化旧软件的Windows表单应用程序。为了在该软件和我的应用程序之间传输信息,我使用剪贴板。单击旧软件上的按钮会将一些信息放入剪贴板。
要使用 Clipboard.GetText ,我应该从Windows窗体中调用它。但我并不想要UI线程上的所有内容。
当我在另一个任务中调用Clipboard.GetText时,我说它应该从STAThread调用Clipboard.GetText。
答案 0 :(得分:4)
你将不得不改变你的期望。标准要求是只有UI线程与剪贴板交互。
从技术上讲,文档中提到的实际要求是只有single-threaded apartment (STA) threads才能访问剪贴板。因为大多数后台线程(如.NET中的ThreadPool类创建的线程)都是多线程单元(MTA)线程,所以它们无法访问剪贴板。你可以通过手动创建自己的STA线程并在其上运行消息泵来解决这个问题,但是使用UI线程要容易得多,这就是每个人所做的事情。
然而,尝试使用剪贴板在两个进程之间共享信息是一个糟糕的设计。剪贴板用于用户存储信息。你写入剪贴板的任何内容都会破坏用户存储的内容。如果您的应用程序执行此操作并覆盖我想要保留的内容,那么我将对您非常愤怒。
流程有更好的方式相互通信;搜索"进程间通信" (缩写为" IPC")用于各种想法。
答案 1 :(得分:2)
您的UI线程是STA。但这并不意味着您必须在UI线程中执行全部您的逻辑。您可以在后台执行除 UI行之外的所有行。通过将您的Clipboard.GetText
调用回调到工作线程中的UI线程(假设您有Form
或任何其他Control
可用),可以在ctrl
变量中进行操作):
//Do something
Func<string> getClipboardText = delegate() { return Clipboard.GetText(); };
string clipboardText = (string)ctrl.Invoke(getClipboardText);
//Do something else
答案 2 :(得分:1)
如果您不想同时使用Windows.Forms或Wpf剪贴板,则可以调用本机剪贴板api,如下所示:
从剪贴板中获取字符串的示例
OpenClipboard(IntPtr.Zero);
var ptr = GetClipboardData(13);
var s = Marshal.PtrToStringUni(ptr);
Marshal.FreeHGlobal(ptr);
CloseClipboard();
我用13作为剪贴板类型(CF_UNICODETEXT) 完整列表,你可以在这里看到: https://msdn.microsoft.com/de-de/library/windows/desktop/ff729168(v=vs.85).aspx