C#console应用程序中使用剪贴板的奇怪行为

时间:2013-12-05 17:49:51

标签: c# .net winforms console clipboard

考虑这个小程序:

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);
    }
}

我运行它,然后从记事本中复制一个字符串。但程序只是从剪贴板中获取一个空字符串并写入“您复制”。

这里有什么问题?是否存在使剪贴板访问在控制台应用程序中表现奇怪的东西?

这是Windows 7 SP1 x86,.NET 4客户端配置文件。

4 个答案:

答案 0 :(得分:10)

使用此功能

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;
  }

在这一行:

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

问题是剪贴板仅适用于某些线程模型(ApartmentState.STA),因此您必须创建一个新线程,并为此代码提供该模型。

答案 1 :(得分:5)

可以重现.NET 4 Client Profile上的代码问题,但是当我切换到.NET 4或4.5时,它会按预期工作。

然而,ClipBoard.GetText() manual州:

  

使用ContainsText方法确定剪贴板是否包含文本数据,然后再使用此方法检索它。

我认为这是一个指示,而不是一个建议,所以,试试这个:

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);
    }
}

它确实显示了复制的文本,但我必须说这会让我的系统在复制一些文本时可怕地挂起。

答案 2 :(得分:3)

这对我有用:

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;
}

答案 3 :(得分:1)

您当前的代码明确等待从"xxPlaceholderxx"到任何内容的第一次更改(您的条件是“不是特定的字符串而不是空”,一旦字符串从"xxPlaceholderxx"更改为任何内容,它就会变为false,包括{ {1}}):

""

您可能需要while (Clipboard.GetText() == "xxPlaceholderxx" && Clipboard.GetText().Trim() != "") (或)而不是和:

||