I used to use a tiny utility called ScriptMan, it would sit in the system tray, and with two clicks it would copy the contents of my selected RTF to the clipboard. I haven't found an equivalent that works on Windows 10 and doesn't monitor the clipboard constantly, so I've tried to write my own in PowerShell. It's worked - almost...
After spending a bit of (way too much of!!) my afternoon/evening on StackOverflow and several other places, I've come up with the following script:
function RTF_to_Clipboard {
$ScriptName = $this.Tag
Write-Host "ScriptName = $ScriptName"
$LabelOutput.Text = "Button $ScriptName clicked"
$ScriptFilePath = "$ScriptsFolder$ScriptName"
Write-Host "$ScriptFilePath = $ScriptFilePath"
#https://stackoverflow.com/questions/65543792/how-to-write-contents-of-an-rtf-file-to- windows-clipboard-with-one-liner
Add-Type -AssemblyName System.Windows.Forms
$rtf = Get-Content -Path $ScriptFilePath
$IsRTF = ($rtf | Select-String '\{\\rtf1' -Quiet)
Write-Host "File $ScriptFilePath" (&{If($IsRTF) {"is"} Else {"IS NOT"}}) "an RTF file."
#[Windows.Forms.Clipboard]::SetText($rtf, [System.Windows.Forms.TextDataFormat]::Rtf)
#[Windows.Forms.Clipboard]::SetDataObject($rtf, $true)
[Windows.Forms.Clipboard]::SetText($rtf, [System.Windows.Forms.TextDataFormat]::Text)
Write-Host $rtf
}
This function is launched by a GUI:
# https://theitbros.com/powershell-gui-for-scripts/
$ScriptsFolder = 'C:\Users\me\OneDrive\Documents\IT\scripts\'
$Scripts = @(
'script 1 - multiline text.rtf',
'script 2 - single line text.rtf',
'script 3 - multiline RTF.rtf'
)
Add-Type -assembly System.Windows.Forms
#Now create the screen form (window) to contain elements:
$main_form = New-Object System.Windows.Forms.Form
#Set the title and size of the window:
$main_form.Text ='Copy Scripts to Clipboard'
$main_form.Width = 600
$main_form.Height = 400
#If the elements on the form are out of window bounds, use the AutoSize property to make the form automatically stretch.
$main_form.AutoSize = $true
#Create button and label for each item in the $Scripts array
$loopcount = 0
foreach($Command in $Scripts)
#for ($loopcount=0; $loopcount -lt $Scripts.count; $loopcount++)
{
$YPos = 25 * $loopcount + 5
$loopcount++
# $Command = $Scripts[$loopcount]
#Now put the button on the form:
Echo "Create button $loopcount for function $Command"
$Button = New-Object System.Windows.Forms.Button
$Button.Location = New-Object System.Drawing.Size(0,$YPos)
$Button.Size = New-Object System.Drawing.Size(60,23)
$Button.Text = "Load"
$Button.Tag = $Command
$Button.Add_Click({
$LabelOutput.Text = "$Command clicked"
Write-Host "$Command clicked"
RTF_to_Clipboard
# RTF_to_Clipboard -ScriptName $Command
})
$main_form.Controls.Add($Button)
#Create a label element on the form:
$Label = New-Object System.Windows.Forms.Label
$Label.Text = $Command
$Label.Location = New-Object System.Drawing.Point(70,$YPos)
$Label.AutoSize = $true
$main_form.Controls.Add($Label)
}
$LabelOutput = New-Object System.Windows.Forms.Label
$LabelOutput.Text = "No command selected yet"
$LabelOutput.Location = New-Object System.Drawing.Point(0,150)
$LabelOutput.AutoSize = $true
$main_form.Controls.Add($LabelOutput)
#Now you can display the form on the screen.
$main_form.ShowDialog()
The form buttons appear to be working, but not copying the text/RTF to the clipboard.
As you can guess from the script names, I have 3 test scripts:
- Multi-line plain text
- Single-line plain text
- Rich Text Format
You can see also from the # remming lines out that I've tried a few methods that others have said they used:
[Windows.Forms.Clipboard]::SetText($rtf, [System.Windows.Forms.TextDataFormat]::Rtf)
This method pastes the plain text into MS word, but doesn't paste anything into NotePad++ or PuTTY (where I need them. The RTF is correct in MS Word (tables preserved), but throws a bunch of errors about "This is not a valid style name."
[Windows.Forms.Clipboard]::SetDataObject($rtf, $true)
The second method copies the single-line text to the clipboard no worries, and it pastes OK in NotePad++, PuTTY and MS Word. The multi-line text and RTF buttons appear to put nothing on the clipboard.
[Windows.Forms.Clipboard]::SetText($rtf, [System.Windows.Forms.TextDataFormat]::Text)
With the last method, the single-line scripts work fine, but the multi-line script all ends up on one line. RTF files get their raw data converted to text - i.e.: a tonne of RTF formating code displayed as plain text; again, all on one line:
{\rtf1\adeflang1025\ansi\ansicpg1252\uc1\adeff0\deff0\stshfdbch0\stshfloch31506\stshfhich31506\stshfbi31506\deflang2057\deflangfe2057\themelang2057\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{*\panose 02020603050405020304}Times New Roman;}{\f0\fbidi \froman\fcharset0\fprq2{*\panose 02020603050405020304}Times New Roman;} {\f37\fbidi \fswiss\fcharset0\fprq2{*\panose 020f0502020204030204}Calibri;}{\f38\fbidi \fswiss\fcharset0\fprq2{*\panose 00000000000000000000}Tahoma;}{\flomajor\f31500\fbidi \froman\fcharset0\fprq2{*\panose 02020603050405020304}Times New Roman;} etc., etc., etc., etc., etc., etc., etc., etc., etc.....
When there is nothing pasting from the clipboard, the PowerShell console is still showing the text value of the files when I call Write-Host $rtf
, so I know that $rtf = Get-Content -Path $ScriptFilePath
worked each time.
Has anyone got any pointers as to how to get the multi-line text copied correctly to the clipboard at least?
I should mention that some of my multi-line scripts (the files that I'm trying to copy to the clipboard) are bash scripts, not sure if their content is breaking the PowerShell clipboard, e.g.:
alias pingAll="while true; do datenow=$(date -D "hh:mm:ss"|cut -c12-19);echo -ne $datenow; echo -ne " -> VPN: "; if ping -q -c 1 -w 5 $VPN_Server_IP>/dev/null; then echo -ne "Up "; else echo -ne " Down"; fi; echo -ne " -> Server A: "; if ping -q -c 1 -w 5 $ServerA_IP>/dev/null; then echo -ne "Up "; else echo -ne " Down"; fi; echo -ne " -> Server B: "; if ping -q -c 1 -w 5 $ServerB_IP>/dev/null ; then echo -ne "Up "; else echo -ne " Down"; fi; echo ; sleep 5; done"
Version = ";grep "<version" /etc/stationInfo.xml |cut -f2 -d">"|cut -f1 -d"<"; echo -ne "Firmware Revision = ";grep "<revision" /etc/stationInfo.xml |cut -f2 -d">"|cut -f1 -d"<"; echo -ne "Firmware Grade = ";grep "<grade" /etc/stationInfo.xml |cut -f2 -d">"|cut -f1 -d"<"; echo -ne "Firmware Date = ";grep "<date" /etc/stationInfo.xml |cut -f2 -d">"|cut -f1 -d"<"'alias fwver='echo -ne "Firmware
I also tried Set-Clipboard -Path "c:\temp\script.rtf"
, but it pastes nothing into NotePad++, and pastes the text or RTF into MS word as an embedded object that needs to be opened to edit, not as inline text.
Any clues how to get this working? Thanks for your help! Cheers.