Clipboard.GetText returns null (empty string)
My clipboard is populated with text, but when I run
string clipboardData = Clipboard.GetText(System.Windows.Forms.TextDataFormat.Text);
I get back an empty string. I've toyed with various forms of the call including:
string clipboardData = Clipboard.GetText();
string clipboardData = Clipboard.GetText(System.Windows.Forms.TextDataFormat.UnicodeText);
But with the same result.
Am I missing something obvious?
Solution 1:
You can only access the clipboard from an STA thread. Rick Brewster ran into this with some refactoring of the regular Edit->Paste command, in Paint.NET.
Code:
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
Code is from Rick. http://forums.getpaint.net/index.php?/topic/13712-/page__view__findpost__p__226140
Update: Jason Heine made a good point of adding ()
after delegate
to fix the ambiguous method error.
Solution 2:
Honestly, I don't know what a STA thread is, but in simple projects it might solve the problem to add [STAThread]
right before the Main
method:
[STAThread]
static void Main(string[] args)
{ (...)
It works for me, so I don't question the method ;)
Further information about the [STAThread]
decorator is on blog post Why is STAThread required?.
Solution 3:
I have written this class, it works, and do the same thing and can be easily improved just adding the method who you need
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
Here is the CSharp Version:
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;
}
}
You can simple use it with: Vb.net:
Dim Clipboard2 As New ClipboardAsync
MessageBox.Show (Clipboard2.ContainsText())
Csharp:
ClipboardAsync Clipboard2 = new ClipboardAsync();
MessageBox.Show (Clipboard2.ContainsText());
Solution 4:
BoltBait's code did not work for IDataObject because data object loses information outside the thread. Everything works fine, if the IDataObject is used only inside the thread like this:
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