Clipboard.GetText返回null(空string)

我的剪贴板填充文本,但是当我运行

string clipboardData = Clipboard.GetText(System.Windows.Forms.TextDataFormat.Text); 

我找回一个空的string。 我玩过各种forms的电话,包括:

 string clipboardData = Clipboard.GetText(); string clipboardData = Clipboard.GetText(System.Windows.Forms.TextDataFormat.UnicodeText); 

但是结果一样。

我错过了什么明显的?

您只能从STA线程访问剪贴板。 里克·布鲁斯特(Rick Brewster)在Paint.NET中对常规编辑 – >粘贴命令进行了一些重构。

码:

 IDataObject idat = null; Exception threadEx = null; Thread staThread = new Thread( delegate () { try { idat = Clipboard.GetDataObject(); } catch (Exception ex) { threadEx = ex; } }); staThread.SetApartmentState(ApartmentState.STA); staThread.Start(); staThread.Join(); // at this point either you have clipboard data or an exception 

代码来自Rick。 http://forums.getpaint.net/index.php?/topic/13712-/page__view__findpost__p__226140

更新 : Jason Heine在delegate之后添加了()以修复模糊的方法错误。

老实说,我不知道STA线程是什么,但是在简单的项目中,它可以解决在Main方法之前添加[STAThread]的问题:

 [STAThread] static void Main(string[] args) { (...) 

它适用于我,所以我不质疑的方法;)


有关[STAThread]装饰器的更多信息在博客文章中为什么要求STAThread?

我已经写了这个类,它工作,并做同样的事情,可以很容易地改善,只是添加你需要的方法

  Private Class ClipboardAsync Private _GetText As String Private Sub _thGetText(ByVal format As Object) Try If format Is Nothing Then _GetText = Clipboard.GetText() Else _GetText = Clipboard.GetText(DirectCast(format, TextDataFormat)) End If Catch ex As Exception _GetText = String.Empty End Try End Sub Public Function GetText() As String Dim instance As New ClipboardAsync Dim staThread As New Thread(AddressOf instance._thGetText) staThread.SetApartmentState(ApartmentState.STA) staThread.Start() staThread.Join() Return instance._GetText End Function Public Function GetText(ByVal format As TextDataFormat) As String Dim instance As New ClipboardAsync Dim staThread As New Thread(AddressOf instance._thGetText) staThread.SetApartmentState(ApartmentState.STA) staThread.Start(format) staThread.Join() Return instance._GetText End Function Private _ContainsText As Boolean Private Sub _thContainsText(ByVal format As Object) Try If format Is Nothing Then _ContainsText = Clipboard.ContainsText() Else _ContainsText = Clipboard.ContainsText(DirectCast(format, TextDataFormat)) End If Catch ex As Exception _ContainsText = False End Try End Sub Public Function ContainsText() As Boolean Dim instance As New ClipboardAsync Dim staThread As New Thread(AddressOf instance._thContainsFileDropList) staThread.SetApartmentState(ApartmentState.STA) staThread.Start() staThread.Join() Return instance._ContainsText End Function Public Function ContainsText(ByVal format As Object) As Boolean Dim instance As New ClipboardAsync Dim staThread As New Thread(AddressOf instance._thContainsFileDropList) staThread.SetApartmentState(ApartmentState.STA) staThread.Start(format) staThread.Join() Return instance._ContainsText End Function Private _ContainsFileDropList As Boolean Private Sub _thContainsFileDropList(ByVal format As Object) Try _ContainsFileDropList = Clipboard.ContainsFileDropList Catch ex As Exception _ContainsFileDropList = False End Try End Sub Public Function ContainsFileDropList() As Boolean Dim instance As New ClipboardAsync Dim staThread As New Thread(AddressOf instance._thContainsFileDropList) staThread.SetApartmentState(ApartmentState.STA) staThread.Start() staThread.Join() Return instance._ContainsFileDropList End Function Private _GetFileDropList As Specialized.StringCollection Private Sub _thGetFileDropList() Try _GetFileDropList = Clipboard.GetFileDropList Catch ex As Exception _GetFileDropList = Nothing End Try End Sub Public Function GetFileDropList() As Specialized.StringCollection Dim instance As New ClipboardAsync Dim staThread As New Thread(AddressOf instance._thGetFileDropList) staThread.SetApartmentState(ApartmentState.STA) staThread.Start() staThread.Join() Return instance._GetFileDropList End Function End Class 

这里是CSharp版本:

 private class ClipboardAsync { private string _GetText; private void _thGetText(object format) { try { if (format == null) { _GetText = Clipboard.GetText(); } else { _GetText = Clipboard.GetText((TextDataFormat)format); } } catch (Exception ex) { //Throw ex _GetText = string.Empty; } } public string GetText() { ClipboardAsync instance = new ClipboardAsync(); Thread staThread = new Thread(instance._thGetText); staThread.SetApartmentState(ApartmentState.STA); staThread.Start(); staThread.Join(); return instance._GetText; } public string GetText(TextDataFormat format) { ClipboardAsync instance = new ClipboardAsync(); Thread staThread = new Thread(instance._thGetText); staThread.SetApartmentState(ApartmentState.STA); staThread.Start(format); staThread.Join(); return instance._GetText; } private bool _ContainsText; private void _thContainsText(object format) { try { if (format == null) { _ContainsText = Clipboard.ContainsText(); } else { _ContainsText = Clipboard.ContainsText((TextDataFormat)format); } } catch (Exception ex) { //Throw ex _ContainsText = false; } } public bool ContainsText() { ClipboardAsync instance = new ClipboardAsync(); Thread staThread = new Thread(instance._thContainsFileDropList); staThread.SetApartmentState(ApartmentState.STA); staThread.Start(); staThread.Join(); return instance._ContainsText; } public bool ContainsText(object format) { ClipboardAsync instance = new ClipboardAsync(); Thread staThread = new Thread(instance._thContainsFileDropList); staThread.SetApartmentState(ApartmentState.STA); staThread.Start(format); staThread.Join(); return instance._ContainsText; } private bool _ContainsFileDropList; private void _thContainsFileDropList(object format) { try { _ContainsFileDropList = Clipboard.ContainsFileDropList; } catch (Exception ex) { //Throw ex _ContainsFileDropList = false; } } public bool ContainsFileDropList() { ClipboardAsync instance = new ClipboardAsync(); Thread staThread = new Thread(instance._thContainsFileDropList); staThread.SetApartmentState(ApartmentState.STA); staThread.Start(); staThread.Join(); return instance._ContainsFileDropList; } private Specialized.StringCollection _GetFileDropList; private void _thGetFileDropList() { try { _GetFileDropList = Clipboard.GetFileDropList; } catch (Exception ex) { //Throw ex _GetFileDropList = null; } } public Specialized.StringCollection GetFileDropList() { ClipboardAsync instance = new ClipboardAsync(); Thread staThread = new Thread(instance._thGetFileDropList); staThread.SetApartmentState(ApartmentState.STA); staThread.Start(); staThread.Join(); return instance._GetFileDropList; } } 

你可以简单的使用它:Vb.net:

 Dim Clipboard2 As New ClipboardAsync MessageBox.Show (Clipboard2.ContainsText()) 

CSHARP:

 ClipboardAsync Clipboard2 = new ClipboardAsync(); MessageBox.Show (Clipboard2.ContainsText()); 

BoltBait的代码不适用于IDataObject,因为数据对象在线程之外丢失信息。 一切工作正常,如果IDataObject只在线程内使用,像这样:

 IDataObject idat = null; Exception threadEx = null; String text = ""; Thread staThread = new Thread( delegate () { try { idat = Clipboard.GetDataObject(); text = idat.GetData(DataFormats.Text) } catch (Exception ex) { threadEx = ex; } }); staThread.SetApartmentState(ApartmentState.STA); staThread.Start(); staThread.Join(); // here you can use text, which contains data from clipboard 

这是一个线程问题。 我们必须得到正确的线程,并通过代表执行。

我正在更新我的属性通过一个计时器每500毫秒消逝。 这里是代码:

  public delegate void ClipboarDelegate(); ClipboarDelegate clipboardDelegate = null; void clipboardTimer_Elapsed(object sender, ElapsedEventArgs e) { if (clipboardDelegate == null) clipboardDelegate = ClipboarDelegateMethod; //Here we get the right thread, most probably the application thread Application.Current.Dispatcher.BeginInvoke(clipboardDelegate); } public void ClipboarDelegateMethod() { try { if (Clipboard.ContainsData(DataFormats.Text)) { //It's important to lock this section lock (ClipboardString) { ClipboardString = Clipboard.GetData(DataFormats.Text) as string; } } } catch { } } 

此外,我用ClipboardString做了一个适当的DependencyProperty:

  public static readonly DependencyProperty ClipboardStringDP = DependencyProperty.Register("ClipboardString", typeof(string), typeof(MainWindow), new UIPropertyMetadata(string.Empty)); public string ClipboardString { get { return (string)this.GetValue(ClipboardStringDP); } set { this.SetValue(ClipboardStringDP, value); } } 

这样它可以绑定到我的文本框在XAML假设我的控制或窗口x:Name="_this"

 <TextBox Name="ClipBoardTextBox" DataContext="{Binding ElementName=_this}" Text="{Binding Path=ClipboardString, Mode=OneWay}"/> 

由于某种原因,BoltBait的代码不起作用(甚至在staThread.Join()之后,idat仍然是空的)。 我只是在staThread委托而不是Clipboard.GetDataObject()的内部做了Clipboard.GetText(),而且工作正常。

谢谢 – 你的代码片段让我有99%的:)