Using the clipboard as input for console tools.
The clipboard can be a very handy source of input for certain console tools. I've written some console C# tools that want to take in a large amount of text from some open document (such as a webpage or a window in my IDE). It would be annoying to have to save the interesting subsection of these open documents to a file, and then load the file up in the tool. Instead, I've used the clipboard. It's very easy to copy the pertinent portion of the document to the clipboard, and then my tool can use the Clipboard class to pull the data down.
Some gotchas:
1. The clipboard class requires Winforms. (I guess it had to live somewhere...)
2. The clipboard class needs to run on an STA thread. (The MSDN docs omit this crucial detail - I've pinged them and they're updating it). Winforms places STAThread on main by default, which is why the clipboard sample code snippets all work in winforms.
3. The clipboard can store multiple formats simultaneously. Be sure to pull the right format. For most console based tools, it's probably just DataFormats.Text format.
4. Recognize the limitations. The clipboard can be nice for end-user interaction, but it does not work well if tools need to chain together. For any wide-scale application, the clipboard should not be the only form of input. Check out demo #2 below.
Below is a sample C# console app that takes strips all formatting from the clipboard. It takes input from the clipboard, clears all other formatting, and then places the input back on in a text-only format. Note that this is a C# console application, and not a winforms app.
Demo #1
1. Compile like so: csc t.cs /debug+ /r:System.Windows.Forms.dll
2. Copy some rich text (such as this blog entry) to the clipboard. Paste in Word and you'll notice the formatting is all there.
3. run the app below from the console.
4. Paste again in word, and you'll notice the formatting is all stripped.
// Simple tool to strip all formatting from clipboard.
using System;
using System.Windows.Forms;
class Program
{
[STAThread()]
static void Main(string[] args)
{
Console.WriteLine("Strip formatted data from the clipboard.");
IDataObject iData = Clipboard.GetDataObject();
string s = (string) iData.GetData(DataFormats.Text);
Clipboard.Clear();
Clipboard.SetDataObject(s, true);
}
}
Demo #2:
The point of this entry is that the clipboard is sometimes a good source of text input. Other forms of text input (like files, strings, and the keyboard) come as a TextReader, so it's natural to want to view the clipboard as a TextReader too. This also makes it easy for tools to multiplex between getting input from the clipboard versus a file. The following snippet shows building a TextReader around clipboard input. Arg[0] is the input parameter. If it's "[clipboard]" then the tool uses a Clipboard-backed TextReader, else it treats Arg[0] as a filename and gets a TextReader for the file.
// Simple tool to TextReader for Clipboard data.
using System;
using System.Windows.Forms;
using System.IO;
class Program
{
// Expose Clipboard as a TextReader.
static class ClipboardTextReaderFactory
{
static public TextReader GetReader()
{
IDataObject iData = Clipboard.GetDataObject();
string s = (string) iData.GetData(DataFormats.Text);
if (s == null) { s = ""; }
return new StringReader(s);
}
}
[STAThread()]
static void Main(string[] args)
{
Console.WriteLine("Print input.");
TextReader r = (args[0] == "[clipboard]") ?
ClipboardTextReaderFactory.GetReader() : // Clipboard is input source
new StreamReader(args[0]);
Console.WriteLine(r.ReadToEnd());
}
}
Comments
- Anonymous
August 22, 2005
Here's my sample code for a tool to catch blog plagiarism that I described earlier. In retrospect, it... - Anonymous
August 24, 2005
Here's my sample code for a tool to catch blog plagiarism that I described earlier. In retrospect, it...