23

EDIT: 23 Oct 2020

See postanote's answer.

EDIT: 14 May 2015

After 3 years, I thought I would share my ClipboardModule (I hope I am allowed to):

Add-Type -AssemblyName System.Windows.Forms

Function Get-Clipboard {
    param([switch]$SplitLines)

    $text = [Windows.Forms.Clipboard]::GetText();
    
    if ($SplitLines) {
        $xs = $text -split [Environment]::NewLine
        if ($xs.Length -gt 1 -and -not($xs[-1])) {
            $xs[0..($xs.Length - 2)]
        } else {
            $xs
        }
    } else {
        $text
    }
}

function Set-Clipboard {
    $in = @($input)

    $out = 
        if ($in.Length -eq 1 -and $in[0] -is [string]) { $in[0] }
        else { $in | Out-String }
    
    if ($out) {
        [Windows.Forms.Clipboard]::SetText($out);
    } else {
        # input is nothing, therefore clear the clipboard
        [Windows.Forms.Clipboard]::Clear();
    }
}


function GetSet-Clipboard {
    param([switch]$SplitLines, [Parameter(ValueFromPipeLine=$true)]$ObjectSet)

    if ($input) {
        $ObjectSet = $input;
    }

    if ($ObjectSet) {
        $ObjectSet | Set-Clipboard
    } else {
        Get-Clipboard -SplitLines:$SplitLines
    }
}

Set-Alias cb GetSet-Clipboard

Export-ModuleMember -Function *-* -Alias *

I usually use the cb alias (for GetSet-Clipboard) because it is two way i.e can get or set the clipboard:

cb                # gets the contents of the clipboard
"john" | cb       # sets the clipboard to "john"
cb -s             # gets the clipboard and splits it into lines
Tahir Hassan
  • 5,715
  • 6
  • 45
  • 65
  • Why do you not want to use `clip`? – Caleb Jares Oct 29 '12 at 19:15
  • Caleb - So I can see the output on the command line too. – Tahir Hassan Oct 30 '12 at 10:04
  • 4
    Tahir, what's wrong with `Get-Foo | tee -v output; $output | clip` then? – Joey Oct 30 '12 at 11:24
  • 1
    Because clip is not part of PowerShell - I don't have it on my computer. – Tahir Hassan Oct 30 '12 at 11:32
  • 3
    @TahirHassan CLIP.EXE should be available on Vista and newer. – Thorbjørn Ravn Andersen Jan 17 '13 at 14:40
  • 1
    @ThorbjørnRavnAndersen - Today I saw that clip.exe not available on Windows 8. – Panayot Karabakalov Feb 11 '13 at 00:34
  • @PanayotKarabakalov just noticed it wasn't there (and where did you look?) or read on a microsoft link that it was gone for good? – Thorbjørn Ravn Andersen Feb 11 '13 at 00:56
  • @ThorbjørnRavnAndersen - Thanks for the response. Can you post the link you mention? I not use Windows 8, only throubleshoot users under it. If I s'd trust to this: http://www.thefiledb.com/filedatabase/windows8/clip.exe-id58812/ the clip.exe s'd be there. – Panayot Karabakalov Feb 11 '13 at 02:00
  • 1
    @PanayotKarabakalov I use Win8, and clip is available –  Apr 22 '13 at 17:19
  • 1
    @Joe Yes, thanks, now I know, the problem was that in Win8 we need absolute path to clip.exe – Panayot Karabakalov Apr 23 '13 at 03:47
  • @TahirHassan another more robust version invokes Powershell command line and it is only 6 lines of code [PoshCode](http://poshcode.org/2150) – Jon Feb 03 '15 at 04:15
  • @Jon Yes, that solution is shorter but it does not have the option of splitting the string into lines, not does it have the option of setting the clipboard or combine the two functions into a `GetSet` function, which I have aliased as `cb`. – Tahir Hassan Nov 10 '15 at 15:54
  • Thanks. : ) Works good. – Tobias Hochgürtel Mar 12 '16 at 18:19
  • This raises an error if the incoming argument is null. – John Zabroski Dec 02 '16 at 15:33
  • @JohnZabroski - I tried $null | cb and it returned what was on the clipboard. – Tahir Hassan Dec 02 '16 at 16:32
  • @TahirHassan $null | Set-Clipboard directly doesnt work. cb is a combination of get and set, which is why it behaves that way. – John Zabroski Dec 02 '16 at 16:36
  • @JohnZabroski - I have fixed fixed this issue. I always use the alias `cb` so I have never run into this issue. – Tahir Hassan Dec 04 '16 at 00:49
  • Take a look at Lee Holme's recipe from the PowerShell Cookbook: [Set-Clipboard](http://poshcode.org/2219). You can use at as Set-Clipboard.ps1, or just drop the code inside a PowerShell function ([here's an example](https://benmccormack.kilnhg.com/Code/Public/Group/WindowsPowerShell/File/Common.ps1?rev=37c866399f52#151-217) from my PowerShell profile). To be sure, it doesn't automatically tee the output, but that should be easy enough to add. I originally learned of Lee Holme's solution from [this answer](https://stackoverflow.com/a/14529996/166258). – Ben McCormack Jan 26 '13 at 19:08

6 Answers6

22

If you have WMF 5.0, PowerShell contains two new cmdlets:

get-clipboard and set-clipboard

Mark Minasi
  • 403
  • 4
  • 9
  • You are one hundred percent right, my friend. But I got spanked the last time I used an alias in a Stack Overflow answer. . Tahir refers to the built-in scb and gcb cmdlets. What's even neater about them is that they're "clipboard smart" in a way that clip.exe never was. – Mark Minasi Feb 10 '16 at 21:32
  • Can you please explain this for those of us who are new to all of this? – Bruno Bronosky Aug 03 '18 at 10:46
3

EDIT: Please look at question instead for solution.

Here is my solution:

Add-Type -AssemblyName 'System.Windows.Forms'

filter Set-Clipboard {
    begin {
        $cp = @()
    }
    process {
        $_ | Tee-Object -Variable 'cp0'
        $cp = $cp + @($cp0);
    }
    end {
        $str = ($cp | Out-String).ToString();

        [Windows.Forms.Clipboard]::Clear();

        if ( ($str -ne $null) -and ($str -ne '') ) {
            [Windows.Forms.Clipboard]::SetText( $str )
        }

        $cp = @()
    }
}

This collects all the objects in an array, $cp. We use Tee-Object to redirect the current element, $_, to both the next process and to store it in the array, $cp. Lastly, once the process is finished we set the clipboard's text.

I have used it in the following way:

dir -Recurse | Set-Clipboard | Select 'Name'

And it seems to work.

To use a function instead:

function Set-Clipboard-Func {
    $str = $input | Out-String

    [Windows.Forms.Clipboard]::Clear();

    if ( ($str -ne $null) -and ($str -ne '') ) {
        [Windows.Forms.Clipboard]::SetText( $str )
    }
}
Tahir Hassan
  • 5,715
  • 6
  • 45
  • 65
  • There is a nice implementation here http://stackoverflow.com/questions/1567112/convert-keith-hills-powershell-get-clipboard-and-set-clipboard-to-a-psm1-script – EBGreen Oct 29 '12 at 19:07
  • There;'s no extra benefit of using the Filter keyword, on the contrary, you should use Function instead. – Shay Levy Oct 29 '12 at 20:04
  • 2
    I can see the benefit in only setting the clipboard data if the data is not empty or null, but what's the point of first clearing the clipboard? – Sam Aug 15 '13 at 01:40
  • It might be necessary to do "`Add-Type -Assembly PresentationCore`" before Windows.Forms.Clipboard is accessible. Otherwise the result may be *"Unable to find type [System.Windows.Clipboard]: make sure that the assembly containing this type is loaded."*. – Peter Mortensen Dec 22 '14 at 18:00
3

Powershell version 6.1 removed this commandlet, so it is no longer built-in.

Instead, you need to install the ClipboardText package. In Powershell's console type:

Install-Module -Name ClipboardText

Then you can use:

 Set-ClipboardText "hello clipboard"
 Get-ClipboardText

Here is the github issue with the maintainers of Powershell redirecting you to use the ClipboardText package.

Donal
  • 8,430
  • 3
  • 16
  • 21
1

Native clip cmdlets in PSv7

$Host
# Results
<#
Name             : ConsoleHost
Version          : 7.0.3
InstanceId       : 54be9bfd-799d-4213-a13a-22403c1d9ed8
UI               : System.Management.Automation.Internal.Host.InternalHostUserInterface
CurrentCulture   : en-US
CurrentUICulture : en-US
PrivateData      : Microsoft.PowerShell.ConsoleHost+ConsoleColorProxy
DebuggerEnabled  : True
IsRunspacePushed : False
Runspace         : System.Management.Automation.Runspaces.LocalRunspace
#>

Get-Command -Name '*clip*'|Format-Table -a
# Results
<#
CommandType Name                         Version        Source
----------- ----                         -------        ------
Function    Get-Clipboard                1.3.6          PowerShellCookbook
Function    Set-Clipboard                1.3.6          PowerShellCookbook
Function    Start-ClipboardHistoryViewer 0.0            ModuleLibrary
Cmdlet      Get-Clipboard                7.0.0.0        Microsoft.PowerShell.Management
Cmdlet      Set-Clipboard                7.0.0.0        Microsoft.PowerShell.Management
Cmdlet      Set-UDClipboard              2.9.0          UniversalDashboard
Application clip.exe                     10.0.19041.1   C:\WINDOWS\system32\clip.exe
Application ClipRenew.exe                10.0.19041.1   C:\WINDOWS\system32\ClipRenew.exe
Application ClipUp.exe                   10.0.19041.488 C:\WINDOWS\system32\ClipUp.exe
Application rdpclip.exe                  10.0.19041.423 C:\WINDOWS\system32\rdpclip.exe
#>
postanote
  • 15,138
  • 2
  • 14
  • 25
0
get-clipboard

skips newline characters when text is entered sequentially. I use

[System.Windows.Forms.Clipboard]::GetText()

as before.

Garric
  • 591
  • 3
  • 10
0

Now that Get-clipboard and Set-Clipboard are built in PSv7 You can have this function in your profile: "C:\Users<USER_ID>\Documents\WindowsPowerShell\Microsoft.PowerShellISE_profile.ps1"

function To-Notepad {
    param(
        [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
        [object]
        $InputObject
    )
  begin   { $objs = @() }
  process { $objs += $InputObject }
  end {
        $old = Get-clipboard # store current value
        $objs | out-string -width 1000 | Set-Clipboard
        & "notepad2" /c
        sleep -mil 500
        $old | Set-Clipboard # restore the original value
  }
}

And then use in this way:

dir -Path C:\Temp | To-Notepad