How to copy colorized script from PowerShell ISE

How to copy colorized script from PowerShell ISE

Rate This
  • Comments 12

UPDATED Feb-03-2009:

Lee Holmes has posted an updated version of the script which does a much better job of HTML copy-pasting. It can also produce line numbers and has a number of other improvements.

 

In the previous article we demonstrated how to use Console-Copy script to make a colorized copy of console screen and place it in the system clipboard. Now what about doing the same thing with these nice looking colorized scripts that you can see in PowerShell ISE? Direct copy with Ctrl-C will copy just text without colorization. But the cool thing about PowerShell ISE is its great extensibility, which means that when you need a feature – you just script it! Let’s follow this path and see what we can learn on the way.

Let’s start from end and figure out how we attach a script to PowerShell ISE user interface. In the example below we create a new menu item which will be displayed as Copy Script menu command under Custom menu group. Clicking on this menu will automatically execute the Copy-Script function. The third parameter sets the hot key as you probably have already guessed. If you don’t want any hot key then just set its value to $null.

$psise.CustomMenu.Submenus.Add("Copy Script", {Copy-Script}, "Shift+Ctrl+S")

Now to the script itself. First, you should check whether there is any script window opened at all.


function Copy-Script
{
    if (-not $psise.CurrentOpenedFile)
    {
        Write-Error 'No script is available for copying.'
        return
    }

If there is a script window opened then let’s get the text from the editor and do the parsing.

    $text = $psise.CurrentOpenedFile.Editor.Text

    trap { break }

    # Do syntax parsing.
    $errors = $null
    $tokens = [system.management.automation.psparser]::Tokenize($Text, [ref] $errors)

Parser can throw, that’s why we need to set error trapping before we call it.

We can ignore $errors for this particular task as the only thing we care is the set of tokens to use for colorization. Here is a list of tokens that PowerShell code can have:

PS D:\> [Enum]::GetNames([System.Management.Automation.PSTokenType])
Unknown
Command
CommandParameter
CommandArgument
Number
String
Variable
Member
LoopLabel
Attribute
Type
Operator
GroupStart
GroupEnd
Keyword
Comment
StatementSeparator
NewLine
LineContinuation
Position

The parser will return a set of tokens which we can iterate through and generate colored RTF blocks and HTML spans using the same technique as described in Colorized capture of console screen in HTML and RTF.

Once we are done, we should grab System.Windows.Clipboard and store our data, which will come in three flavors: UnicodeText, HTML and RTF:

    $dataObject = New-Object Windows.DataObject
    $dataObject.SetText([string]$text, [Windows.TextDataFormat]"UnicodeText")
    $dataObject.SetText([string]$rtf, [Windows.TextDataFormat]"Rtf")
    $dataObject.SetText([string]$html, [Windows.TextDataFormat]"Html")
    [Windows.Clipboard]::SetDataObject($dataObject, $true)

Full script attached.

Enjoy!
Vladimir Averkin
Windows PowerShell Team

Attachment: Copy-Script.zip
Leave a Comment
  • Please add 4 and 2 and type the answer here:
  • Post
  • What's the purpose of $psise.CustomMenu.Submenus.Clear() in Copy-Script.ps1? It removes every entry from Custom menu in PowerShell ISE before adding "Copy Script".

  • PingBack from http://www.alvinashcraft.com/2009/01/13/dew-drop-january-13-2009/

  • To Alexandar:

    My bad. I have put $psise.CustomMenu.Submenus.Clear() line when developing this script, to reset the menu  before each run. Now it is, of course, not necessary. I will update the script.

    Thanks for noticing this!

    Vladimir

  • To Vladimir:

    Wow! You responded to my post with a solution in lightning speed!  You guys rock!  I've been a user/fan of PS since the V1 beta and I still believe that this is the most visionary product offered by Microsoft.  Keep up the good work and I'll keep turning my peers into fans...

    Thanks!

    T-Bone

  • Just come across an odd problem with Live Writer. Experimenting with the copy-script function from http

  • Just come across an odd problem with Live Writer. Experimenting with the copy-script function from http

  • As someone who does a far amount of downloading of stuff – especially technical documents etc I was interested

  • That happens with an older version of LiveWriter. When the script creates HTML for system clipboard, it does not add the special clipboard header which generally is required, but most application can do without it. Previous versions of LiveWriter were not supporting pasting HTML without proper clipboard header, but the new version does. Try to download the latest version of LiveWriter and the problem should go away.

    Thanks,

    Vladimir Averkin

    Windows PowerShell team

  • Great stuff, but Windows Live Writer fails when I try to paste special.

    If I fix these lines (save the html as unicode text on the clipboard), it works.

       $dataObject = New-Object Windows.DataObject

       #$dataObject.SetText([string]$text, [Windows.TextDataFormat]"UnicodeText")

       $rtf = $rtfBuilder.ToString()

       #$dataObject.SetText([string]$rtf, [Windows.TextDataFormat]"Rtf")

       $html = $htmlBuilder.ToString()

       $dataObject.SetText([string]$html, [Windows.TextDataFormat]"UnicodeText")

  • Maybe that last comment slipped away too fast - but according to my WLW version 14.0.8064.206 da, there are no newer versions.

  • Hi Vladimir,

    Thanks for the script, I've found it very helpful!  However I noticed that in the RTM version of Powershell ISE the properties of the $psise object aren't quite the same as they were in the CTP, so I got the following error:

    You cannot call a method on a null-valued expression.

    With the help of this article (powershell.com/.../what-happened-to-a-custommenu-property.aspx) I managed to get it to work by changing these three lines:

    Line 41: if (-not $psise.CurrentFile)

    Line 47: $text = $psise.CurrentFile.Editor.Text

    Line 133: $psISE.CurrentPowerShellTab.AddOnsMenu.Submenus.Add("Copy Script", {Copy-Script}, $null)

    Hope this helps anyone else who has the same problem.

    Cheers,

    D

  • I've made some further modifications to allow getting the Formatted Code into a state that can be pasted directly into Lync, or OneNote 2010. Previously this would have been done via Pasting into Word and Copying it out again.

    ...

       [Windows.Clipboard]::SetDataObject($dataObject, $true)

       $word = New-Object -ComObject Word.Application

       $doc = $word.Documents.Add()

       $a = $word.Selection.Paste()

       $word.Selection.Start = 0

       $a = $word.Selection.Copy()

       $a = $doc.Undo()

       $wdNoSave = [microsoft.office.interop.word.WdSaveOptions]::wdDoNotSaveChanges

       $doc.Close([ref]$wdNoSave)

       $doc = $null

       $word.Quit([ref]$wdNoSave)

       $word = $null

       'The script has been copied to clipboard.'

    ...

Page 1 of 1 (12 items)