3

I'm programming a Windows form application which automates an old software. For transferring information between that software and my application I use Clipboard. Clicking a button on old software puts some information in the clipboard.

For using Clipboard.GetText I should call it from a windows form. But I don't want everything on UI thread.

When calling Clipboard.GetText in another task I got it says you should call Clipboard.GetText from an STAThread.

Milad
  • 539
  • 8
  • 21

3 Answers3

5

You are going to have to alter your expectations. It is a standard requirement that only the UI thread interact with the clipboard.

Technically speaking, the actual requirement, as called out in the documentation, is that only single-threaded apartment (STA) threads can access the clipboard. Because most background threads, like those created by the ThreadPool class in .NET, are multi-threaded apartment (MTA) threads, they cannot access the clipboard. You can work around this by manually creating your own STA thread and running a message pump on it, but it is far easier to just use the UI thread, so that's what everyone does.

However, it is a poor design to begin with to try and use the clipboard to share information between two processes. The clipboard is intended for the user to store information. Anything you write to the clipboard will clobber whatever the user had stored there. If your application does this, and overwrites something that I wanted to keep, I'm going to be exceptionally furious with you.

There are better ways for processes to communicate with each other; search for "interprocess communication" (abbreviated "IPC") for various ideas.

Community
  • 1
  • 1
Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
  • Thanks for your response. Actually it's not an application for a customer. There is an old software which connects to mainframe and gets Flights Information. It's a terminal. We write an application and put it on a server beside the old software which connects to the mainframe. – Milad Nov 27 '16 at 11:54
  • Well, that's great, it solves the furious customer problem, but it doesn't change the fundamental issues that (1) the clipboard is not designed to be used from multiple threads, and (2) there are a series of vastly better and more appropriate mechanisms for cross-process communication than the clipboard. – Cody Gray - on strike Nov 27 '16 at 11:58
  • You are totally right, but I'm restricted to the fact that I cannot change an old program(which is a closed source with only few technical documentation.) – Milad Nov 27 '16 at 12:00
2

Your UI thread is a STA. But that doesn't mean you have to execute all your logic in the UI thread. You can execute all lines except the UI line in the background. That is possible by marshalling your Clipboard.GetText call back to the UI thread from your worker thrad (assuming you have a Form or any other Controlavailable - here in the ctrlvariable):

//Do something
Func<string> getClipboardText = delegate() { return Clipboard.GetText(); };
string clipboardText = (string)ctrl.Invoke(getClipboardText);
//Do something else
Sefe
  • 13,731
  • 5
  • 42
  • 55
  • Thanks for your response @Sefe. But in my case Maksim answer suites my problem better. Thank you so much. – Milad Nov 27 '16 at 12:51
1

If you don't want to use neither Windows.Forms or Wpf clipboard, you can invoke native clipboard api, as shown here:

How can I copy a string to clipboard within my console app WITHOUT adding a reference to System.Windows.Forms?

Sample for getting string from clipboard

        OpenClipboard(IntPtr.Zero);

        var ptr = GetClipboardData(13);
        var s = Marshal.PtrToStringUni(ptr);
        Marshal.FreeHGlobal(ptr);
        CloseClipboard();

i have used 13 as clipboard type (CF_UNICODETEXT) Full list you could see here: https://msdn.microsoft.com/de-de/library/windows/desktop/ff729168(v=vs.85).aspx

Community
  • 1
  • 1
Maksim Simkin
  • 9,561
  • 4
  • 36
  • 49