Dwarfsoft [GPA]

PowerShell PowerISE Copy-Script Add-On

by on Nov.16, 2012, under Uncategorized


Print This Post Print This Post

One of the most useful things I get to use in day to day scripting is Copy-Script. It is a script that I originally picked up from this msdn blog. I have since made a couple of modifications to allow me to reload it with the rest of my profile, as well as my most recent addition: Converting the Formatted Text to Word Document format.

The reason I needed to use Word Document format was due to OneNote and Lync not taking the RTF formatted data until it had been pasted and copied out of Microsoft Word. Therefore I added the following process into the end of the script:

    #...
    [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.'
    #...

The Full Text of the Script is as follows:

##############################################################################################################
# Copy-Script.ps1
#
# The script entire contents of the currently selected editor window to system clipboard.
# The copied data can be pasted into any application that supports pasting in UnicodeText, RTF or HTML format.
# Text pasted in RTF or HTML format will be colorized.
#
 
 
# Create RTF block from text using named console colors.
#
function Append-RtfBlock ($block, $tokenColor)
{
    $colorIndex = $rtfColorMap.$tokenColor
    $block = $block.Replace('\','\\').Replace("`r`n","\cf1\par`r`n").Replace("`t",'\tab').Replace('{','\{').Replace('}','\}')
    $null = $rtfBuilder.Append("\cf$colorIndex $block")
}
 
# Generate an HTML span and append it to HTML string builder
#
function Append-HtmlSpan ($block, $tokenColor)
{
  if ($tokenColor -eq 'NewLine')
  {
    $null = $htmlBuilder.Append("<br>")
  }
  else
  {
    $block = $block.Replace('&','&amp;').Replace('>','&gt;').Replace('<','&lt;')
    if (-not $block.Trim())
    {
        $block = $block.Replace(' ', '&nbsp;')
    }
    $htmlColor = $psise.Options.TokenColors[$tokenColor].ToString().Replace('#FF', '#')
    $null = $htmlBuilder.Append("<span style='color:$htmlColor'>$block</span>")
  }
}
 
function Copy-Script
{
    if (-not $psise.CurrentFile)
    {
        Write-Error 'No script is available for copying.'
        return
    }
 
    if ($psise.CurrentFile.Editor.SelectedText -eq "")
    {
      $text = $psise.CurrentFile.Editor.Text
    } else
    {
      $text = $psise.CurrentFile.Editor.SelectedText
    }
 
    trap { break }
 
    # Do syntax parsing.
    $errors = $null
    $tokens = [system.management.automation.psparser]::Tokenize($Text, [ref] $errors)
 
    # Set the desired font and font size
    $fontName = 'Lucida Console'
    $fontSize = 10
 
    # Initialize HTML builder.
    $htmlBuilder = new-object system.text.stringbuilder
    $null = $htmlBuilder.AppendLine("<p style='MARGIN: 0in 10pt 0in;font-family:$fontname;font-size:$fontSize`pt'>")
 
    # Initialize RTF builder.
    $rtfBuilder = new-object system.text.stringbuilder
    # Append RTF header
    $null = $rtfBuilder.Append("{\rtf1\fbidis\ansi\ansicpg1252\deff0\deflang1033{\fonttbl{\f0\fnil\fcharset0 $fontName;}}")
    $null = $rtfBuilder.Append("`r`n")
    # Append RTF color table which will contain all Powershell console colors.
    $null = $rtfBuilder.Append("{\colortbl ;")
    # Generate RTF color definitions for each token type.
    $rtfColorIndex = 1
    $rtfColors = @{}
    $rtfColorMap = @{}
    [Enum]::GetNames([System.Management.Automation.PSTokenType]) | % {
        $tokenColor = $psise.Options.TokenColors[$_];
        $rtfColor = "\red$($tokenColor.R)\green$($tokenColor.G)\blue$($tokenColor.B);"
        if ($rtfColors.Keys -notcontains $rtfColor)
        {
            $rtfColors.$rtfColor = $rtfColorIndex
            $null = $rtfBuilder.Append($rtfColor)
            $rtfColorMap.$_ = $rtfColorIndex
            $rtfColorIndex ++
        }
        else
        {
            $rtfColorMap.$_ = $rtfColors.$rtfColor
        }
    }
    $null = $rtfBuilder.Append('}')
    $null = $rtfBuilder.Append("`r`n")
    # Append RTF document settings.
    $null = $rtfBuilder.Append('\viewkind4\uc1\pard\f0\fs20 ')
 
    $position = 0
    # Iterate over the tokens and set the colors appropriately.
    foreach ($token in $tokens)
    {
        if ($position -lt $token.Start)
        {
            $block = $text.Substring($position, ($token.Start - $position))
            $tokenColor = 'Unknown'
            Append-RtfBlock $block $tokenColor
            Append-HtmlSpan $block $tokenColor
        }
 
        $block = $text.Substring($token.Start, $token.Length)
        $tokenColor = $token.Type.ToString()
        Append-RtfBlock $block $tokenColor
        Append-HtmlSpan $block $tokenColor
 
        $position = $token.Start + $token.Length
    }
 
    # Append HTML ending tag.
    $null = $htmlBuilder.Append("</p>")
 
    # Append RTF ending brace.
    $null = $rtfBuilder.Append('}')
 
    # Copy console screen buffer contents to clipboard in three formats - text, HTML and RTF.
    #
    $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]"Html")
 
    [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.'
}
 
#$psise.CustomMenu.Submenus.Add("Copy Script", {Copy-Script}, $null)
if ($psise.PowerShellTabs[0].DisplayName -eq "PowerShell 1")
{
   $tabs = [Microsoft.PowerShell.Host.ISE.PowerShellTab]$psise.PowerShellTabs[0]
   $menu = [Microsoft.PowerShell.Host.ISE.ISEMenuItem]$tabs.AddOnsMenu
   $ret = $menu.Submenus.Add("Copy Script",{Copy-Script},$null)
 
} else {
  $ret = $psise.CustomMenu.Submenus.Add("Copy Script", {Copy-Script}, $null)
}

Cheers, Chris


Looking for something?

Use the form below to search the site:

Still not finding what you're looking for? Drop a comment on a post or contact us so we can take care of it!