Convert Keith Hill's PowerShell Get-Clipboard and Set-Clipboard to a PSM1 script
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() {
Param(
[Parameter(ValueFromPipeline=$true)]
[string] $text
)
Add-Type -AssemblyName System.Windows.Forms
$tb = New-Object System.Windows.Forms.TextBox
$tb.Multiline = $true
$tb.Text = $text
$tb.SelectAll()
$tb.Copy()
}
See the bottom section for a cross-edition, cross-platform module that offers clipboard text support in PowerShell Core and in Windows PowerShell v2 - v4.
An attempt to summarize the state of affairs and options as of Windows PowerShell v5.1 / PowerShell Core v6.1.0:
Windows PowerShell v5.0+: Use the built-in
Get-Clipboard
andSet-Clipboard
cmdlets.Windows PowerShell v4.0- (v1 - v4.0): has no built-in cmdlets for interacting with the clipboard, but there are workarounds:
- Use PowerShell Community Extensions (PSCX; http://pscx.codeplex.com/), which come with several clipboard-related cmdlets that go beyond just handling text.
Pipe to the standard command-line utility
clip.exe
(W2K3+ server-side, Vista+ client-side)[1]:Note: Aside from the encoding issues discussed below,
... | clip.exe
invariably appends a trailing newline to the input; the only way to avoid that is to use a temporary file whose content is provided via cmd's<
input redirection - see theSet-ClipboardText
function below.If only ASCII-character (7-bit) support is needed: works by default.
If only OEM-encoding (8-bit) support (e.g., IBM437 in the US) is needed, run the following first:
$OutputEncoding = [System.Text.Encoding]::GetEncoding([System.Globalization.CultureInfo]::CurrentCulture.TextInfo.OEMCodePage)
If full Unicode support is needed, a UTF-16 LE encoding without BOM must be used; run the following first:
$OutputEncoding = New-Object System.Text.UnicodeEncoding $false, $false # UTF-16 encoding *without BOM*
Example to test with (the PS console will display the Asian chars. as "??", but still handle them correctly - verify clipboard content in Notepad, for instance):
"I enjoyed Thomas Hübl's talk about 中文" | clip # should appear as is on the clipboard
Note: Assigning to
$OutputEncoding
as above works fine in the global scope, but not otherwise, such as in a function, due to a bug as of Windows PowerShell v5.1 / PowerShell Core v6.0.0-rc.2 - see https://github.com/PowerShell/PowerShell/issues/5763- In a non-global context, use
(New-Object ...).psobject.BaseObject
to work around the bug, or - in PSv5+ - use[...]:new()
instead.
- In a non-global context, use
Note:
clip.exe
apparently understands 2 formats:- the system's current OEM codepage (e.g., IBM 437)
- UTF-16 LE ("Unicode")
- Unfortunately,
clip.exe
always treats a BOM as data, hence the need to use a BOM-less encoding. - Note that the above encodings matter only with respect to correctly detecting input; once on the clipboard, the input string is available in all of the following encodings: UTF-16 LE, "ANSI", and OEM.
Use a PowerShell-based solution with direct use of .NET classes:
Note that clipboard access can only occur from a thread in STA (single-threaded apartment) mode - as opposed to MTA (multi-threaded apartment):
- v3: STA is the default (MTA mode can be entered by invoking
powershell.exe
with the-mta
switch). - v2 and v1: MTA is the default; STA mode can be entered by invoking
powershell.exe
with the-sta
switch. - Ergo: Robust functions should be able to access the clipboard from sessions in either mode.
- v3: STA is the default (MTA mode can be entered by invoking
PowerShell Core (multi-platform), as of v6.1.0, has no built-in cmdlets for interacting with the clipboard, not even when run on Windows.
- The workaround is to use platform-specific utilities or APIs - see below.
My ClipboardText
module provides
"polyfill" functions Get-ClipboardText
and Set-ClipboardText
for getting and setting text from the clipboard; they work on Windows PowerShell v2+ as well as on PowerShell Core (with limitations, see below).
In the simplest case (PSv5+ or v3/v4 with the package-management modules installed), you can install it from the PowerShell Gallery from an elevated / sudo
session as follows:
Install-Module ClipboardText
For more information, including prerequisites and manual-installation instructions, see the repo.
Note: Strictly speaking, the functions aren't polyfills, given that their names differ from the built-in cmdlets. However, the name suffix Text was chosen so as to make it explicit that these functions handle text only.
The code gratefully builds on information from various sites, notably @hoge's answer (https://stackoverflow.com/a/1573295/45375) and http://techibee.com/powershell/powershell-script-to-copy-powershell-command-output-to-clipboard/1316
Running on Windows PowerShell v5+ in STA mode:
- The built-in cmdlets (
Get-Clipboard
/Set-Clipboard
) are called behind the scenes.
Note that STA mode (a COM threading model) is the default since v3, but you can opt into MTA (multi-threaded mode) with command-line option-MTA
.
- The built-in cmdlets (
In all other cases (Windows PowerShell v4- and/or in MTA mode, PowerShell Core on all supported platforms):
- Windows:
- A P/Invoke-based solution that calls the Windows API is used, via ad-hoc C# code compiled with
Add-Type
.
- A P/Invoke-based solution that calls the Windows API is used, via ad-hoc C# code compiled with
- Unix-like platforms: Native utilities are called behind the scenes:
- macOS:
pbcopy
andpbpaste
- Linux:
xclip
, if available and installed;
for instance, on Ubuntu, usesudo apt-get xclip
to install.
- macOS:
- Windows:
Set-ClipboardText
can accept any type of object(s) as input (which is/are then converted to text the same way they would render in the console), either directly, or from the pipeline.Invoke with
-Verbose
to see what technique is used behind the scenes to access the clipboard.
[1] An earlier version of this answer incorrectly claimed that clip.exe
:
- always appends a line break when copying to the clipboard (it does NOT)
- correctly handles UTF-16 LE BOMs in files redirected to stdin via <
vs. when input is piped via |
(clip.exe
always copies the BOM to the clipboard, too).
I just blogged how to do this:
http://www.nivot.org/2009/10/14/PowerShell20GettingAndSettingTextToAndFromTheClipboard.aspx
-Oisin