views:

754

answers:

3

I'd like to convert Keith Hill's C# implementation of Get-Clipboard and Set-Clipboard into pure PowerShell as a .PSM1 file.

Is there a way to spin up an STA thread in PowerShell as he does in his Cmdlet when working with the clipboard?

The Blog Post
The Code

+3  A: 

I just blogged how to do this:

http://www.nivot.org/2009/10/14/PowerShell20GettingAndSettingTextToAndFromTheClipboard.aspx

-Oisin

x0n
This doesn't work with large values for $text. Program 'powershell.exe' failed to execute: The filename or extension is too long
spoon16
ouch. well I guess stick with a binary cmdlet, or by starting powershell.exe itself with the -STA flag and using the clipboard methods directly (or use ISE which is in STA mode by default)
x0n
alternatively, you could modify my functions to read/write from a temporary file.
x0n
I just updated my blog post to use a temp file - this avoids your problem. No limit now for text size.
x0n
good thinking !
spoon16
Rather than invoking [windows.forms.clipboard]::SetText() in a child powershell process, it is probably more efficient to use clip.exe.
Brian Reiter
+1  A: 

You should check your host first. ISE already runs STA so there is no need to spin up another thread or shell out (which is an optimization that's on my todo list for PSCX). For the console prompt, which is MTA, then I would shell out to binary code either as Oisin shows or use a simple little C# app like:

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
class OutClipboard {
  [STAThread]
  static void Main() {
    Clipboard.SetText(Console.In.ReadToEnd());
  }
}

And for getting the clipboard contents, Vista and later have clip.exe.

I don't think that even 2.0's advanced functions is ready to let folks party with their own .NET threads in a script.

Keith Hill
At that point I might as well just go with the C# cmdlet. Seems like the best approach given the threading limitations. Is there a way to start a job on an STA thread?
spoon16
Heh, I was just looking through the Jobs docs for that and didn't come across anything that would give you control of that attribute on a job.
Keith Hill
+4  A: 

TextBox doesn't require -STA switch.

function Get-ClipBoard {
    Add-Type -AssemblyName System.Windows.Forms
    $tb = New-Object System.Windows.Forms.TextBox
    $tb.Multiline = $true
    $tb.Paste()
    $tb.Text
}


function Set-ClipBoard($text) {
    Add-Type -AssemblyName System.Windows.Forms
    $tb = New-Object System.Windows.Forms.TextBox
    $tb.Multiline = $true
    $tb.Text = $text
    $tb.SelectAll()
    $tb.Copy()
}
hoge
I'll give this a shot when I get to work. Great idea though.
spoon16
worked... just had to add one line to your script to make sure System.Windows.Forms was loaded
spoon16
Heh, ever escalating techniques. Ok, my next post will be a multi-format clipboard module with no temp files that can handle more than just text.
x0n