Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Strange behaviour with clipboard in C# console application

Consider this small program:

class Program
{
    [STAThread]
    static void Main(string[] args)
    {
        Console.WriteLine("Please copy something into the clipboard.");
        WaitForClipboardChange();
        Console.WriteLine("You copied " + Clipboard.GetText());
        Console.ReadKey();
    }

    static void WaitForClipboardChange()
    {
        Clipboard.SetText("xxPlaceholderxx");
        while (Clipboard.GetText() == "xxPlaceholderxx" && 
               Clipboard.GetText().Trim() != "")
            Thread.Sleep(90);
    }
}

I run it, and I copy a string from Notepad. But the program just gets an empty string from the clipboard and writes "You copied ".

What's the problem here? Is there something that makes clipboard access behave weirdly in a console application?

This is Windows 7 SP1 x86, .NET 4 Client Profile.

like image 491
LTR Avatar asked Dec 05 '13 17:12

LTR


2 Answers

Use this function

static string GetMeText()
  {
     string res = "starting value";
     Thread staThread = new Thread(x => 
       {
         try
         {
             res = Clipboard.GetText();
         }
         catch (Exception ex) 
         {
            res = ex.Message;            
         }
       });
    staThread.SetApartmentState(ApartmentState.STA);
    staThread.Start();
    staThread.Join();
    return res;
  }

In this line:

  Console.WriteLine("You copied " + Clipboard.GetMeText());

The problem is that the clipboard only works with certain threading models (ApartmentState.STA) so you have to make a new thread and give it that model this code does that.

like image 90
Hogan Avatar answered Sep 20 '22 16:09

Hogan


I can reproduce the problem with your code on .NET 4 Client Profile, but when I switch to .NET 4 or 4.5 it works as expected.

However, the ClipBoard.GetText() manual states:

Use the ContainsText method to determine whether the Clipboard contains text data before retrieving it with this method.

I take that as an instruction, not a suggestion, so, try this:

class Program
{
    [STAThread]
    static void Main(string[] args)
    {
        Console.WriteLine("Please copy something into the clipboard.");
        WaitForClipboardChange();
        Console.WriteLine("You copied " + Clipboard.GetText());
        Console.ReadKey();
    }
    static void WaitForClipboardChange()
    {
        Clipboard.Clear();

        while (!Clipboard.ContainsText())
            Thread.Sleep(90);
    }
}

It does show the copied text, although I must say this lets my system hang horribly when I copy some text.

like image 26
CodeCaster Avatar answered Sep 19 '22 16:09

CodeCaster