Domanda

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.

È stato utile?

Soluzione

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.

Altri suggerimenti

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.

This works for me:

static void Main(string[] args)
{
    Console.WriteLine("Please copy something into the clipboard.");
    string text = WaitForClipboardChange();
    Console.WriteLine("You copied " + text);
}
static string WaitForClipboardChange()
{
    string placeholderText = "xxPlaceholderxx";
    Clipboard.SetText(placeholderText);

    string text = null;
    do 
    {
        Thread.Sleep(90);
        text = Clipboard.GetText();
    }
    while (string.IsNullOrWhiteSpace(text) || text.Equals(placeholderText));

    return text;
}

Your current code explicitly waits for first change from "xxPlaceholderxx" to anything (your condition is "not particular string AND not empty" which turns false as soon as string changes from "xxPlaceholderxx" to anything, including ""):

while (Clipboard.GetText() == "xxPlaceholderxx" 
    && Clipboard.GetText().Trim() != "")

You probably want || (or) instead of and:

// assuming System.Windows.Forms.Clipboard
static void WaitForClipboardChange()
{
    Clipboard.SetText("xxPlaceholderxx");
    while (Clipboard.GetText() == "xxPlaceholderxx" 
    || string.IsNullOrWhiteSpace(Clipboard.GetText()))
        Thread.Sleep(90);
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top