PSClip.psm1
# Code from https://gist.github.com/danielmoore/2322634 # Credits for Daniel Moore (https://github.com/danielmoore) Add-Type -Namespace PowershellPlatformInterop -Name Clipboard -MemberDefinition @" [DllImport("user32.dll", SetLastError=true)] public static extern bool EmptyClipboard(); [DllImport("user32.dll", SetLastError=true)] public static extern IntPtr SetClipboardData(uint uFormat, IntPtr hMem); [DllImport("user32.dll", SetLastError=true)] public static extern IntPtr GetClipboardData(uint uFormat); [DllImport("user32.dll", SetLastError=true)] public static extern bool OpenClipboard(IntPtr hWndNewOwner); [DllImport("user32.dll", SetLastError=true)] public static extern bool CloseClipboard(); [DllImport("user32.dll", SetLastError=true)] public static extern uint EnumClipboardFormats(uint format); "@ -ErrorAction SilentlyContinue function Assert-Win32CallSuccess { param( [Switch]$PassThru, [Switch]$NullIsError, [ScriptBlock]$Action) $result = & $Action if($NullIsError -and $result -eq 0 -or -not $NullIsError -and $result -ne 0) { $errorCode = [Runtime.InteropServices.Marshal]::GetLastWin32Error() [Runtime.InteropServices.Marshal]::ThrowExceptionForHR($errorCode) } if ($PassThru) { $result } } function Use-Clipboard { param([ScriptBlock]$Action) if($script:isClipboardOwned) { return & $Action } $script:isClipboardOwned = $true Assert-Win32CallSuccess -NullIsError { [PowershellPlatformInterop.Clipboard]::OpenClipboard([IntPtr]::Zero) } try { & $Action } finally { Assert-Win32CallSuccess -NullIsError { [PowershellPlatformInterop.Clipboard]::CloseClipboard() } $script:isClipboardOwned = $false } } function Clear-Clipboard { Use-Clipboard { Assert-Win32CallSuccess { [PowershellPlatformInterop.Clipboard]::EmptyClipboard() } } } $ansiTextFormat = 1 $unicodeTextFormat = 13 function Set-ClipboardText { param([Parameter(ValueFromPipeline=$true)][string]$Value) begin { $textToCopy = $null } process { if($textToCopy -ne $null) { $textToCopy = $textToCopy + [Environment]::NewLine; } $textToCopy = $textToCopy + $Value; } end { Use-Clipboard { Clear-Clipboard $ptr = [Runtime.InteropServices.Marshal]::StringToHGlobalUni($textToCopy) Assert-Win32CallSuccess -NullIsError { [PowershellPlatformInterop.Clipboard]::SetClipboardData($unicodeTextFormat, $ptr) } } } } function Get-ClipboardFormats { Use-Clipboard { $prev = 0 while($true) { $prev = Assert-Win32CallSuccess -NullIsError -PassThru { [PowershellPlatformInterop.Clipboard]::EnumClipboardFormats($prev) } if ($prev -eq 0) { break; } $prev } } } function Get-ClipboardText { Use-Clipboard { $formats = Get-ClipboardFormats $clip = if($formats -contains $unicodeTextFormat) { $ptr = Assert-Win32CallSuccess -PassThru -NullIsError { [PowershellPlatformInterop.Clipboard]::GetClipboardData($unicodeTextFormat) } if ($ptr -ne 0) { [Runtime.InteropServices.Marshal]::PtrToStringUni($ptr) } } elseif($formats -contains $ansiTextFormat) { $ptr = Assert-Win32CallSuccess -PassThru -NullIsError { [PowershellPlatformInterop.Clipboard]::GetClipboardData($ansiTextFormat) } if ($ptr -ne 0) { [Runtime.InteropServices.Marshal]::PtrToStringAnsi($ptr) } } $current = 0; while($current -ge 0) { $idx = $clip.IndexOf([System.Environment]::NewLine, $current); if($idx -eq -1) { $clip.Substring($current); $current = $idx } else { $clip.Substring($current, $idx - $current); $current = $idx + 2 } } } } Set-Alias scb Set-ClipboardText Set-Alias gcb Get-ClipboardText |