clips.psm1
using namespace System.Reflection using namespace System.Linq.Expressions using namespace System.Runtime.InteropServices $keys, $types = ($x = [PSObject].Assembly.GetType( 'System.Management.Automation.TypeAccelerators' ))::Get.Keys, @{ ptr = [IntPtr] } $types.Keys.ForEach{ if ($_ -notin $keys) { $x::Add($_, $types.$_) } } function New-Delegate { [CmdletBinding()] param( [Parameter(Mandatory, Position=0)] [ValidateNotNullOrEmpty()] [String]$Module, [Parameter(Mandatory, Position=1)] [ValidateScript({![String]::IsNullOrEmpty($_)})] [ScriptBlock]$Signature ) begin { $kernel32 = @{} [Array]::Find(( Add-Type -AssemblyName Microsoft.Win32.SystemEvents -PassThru ), [Predicate[Type]]{$args[0].Name -eq 'kernel32'} ).GetMethods([BindingFlags]'NonPublic, Static, Public').Where{ $_.Name -cmatch '\AGet(P|M)' }.ForEach{ $kernel32[$_.Name] = $_ } if (( $mod = $kernel32.GetModuleHandle.Invoke($null, @($Module)) ) -eq [IntPtr]::Zero) { throw [DllNotFoundException]::new("Can not find $Module library.") } } process {} end { $funcs = @{} for ($i, $m, $fn, $p = 0, ([Expression].Assembly.GetType( 'System.Linq.Expressions.Compiler.DelegateHelpers' ).GetMethod('MakeNewCustomDelegate', [BindingFlags]'NonPublic, Static') ), [Marshal].GetMethod('GetDelegateForFunctionPointer', ([IntPtr])), $Signature.Ast.FindAll({$args[0].CommandElements}, $true).ToArray(); $i -lt $p.Length; $i++ ) { $fnret, $fname = ($def = $p[$i].CommandElements).Value if (( $fnsig = $kernel32.GetProcAddress.Invoke($null, @($mod, $fname)) ) -eq [IntPtr]::Zero) { throw [InvalidOperationException]::new("Can not find $fname signature.") } $fnargs = $def.Pipeline.Extent.Text [Object[]]$fnargs = (( ($fnargs -replace '\[|\]' -split ',\s+?') + $fnret ), $fnret)[[String]::IsNullOrEmpty($fnargs)] $funcs[$fname] = $fn.MakeGenericMethod( [Delegate]::CreateDelegate([Func[[Type[]], Type]], $m).Invoke($fnargs) ).Invoke([Marshal], $fnsig) } Set-Variable $Module -Value $funcs -Scope Script -Force } } function Get-Clipboard { [CmdletBinding()]param() begin { New-Delegate kernel32 { ptr GlobalLock([ptr]) bool GlobalUnlock([ptr]) } New-Delegate user32 { bool CloseClipboard uint EnumClipboardFormats([uint]) ptr GetClipboardData([uint]) bool OpenClipboard([ptr]) } function private:Test-ClipFormat([UInt32]$Format) { process { while (0 -ne ($fmt = $user32.EnumClipboardFormats.Invoke($fmt))) { if ($fmt -eq $Format) { return $true } } return $false } } } process {} end { if ($user32.OpenClipboard.Invoke([IntPtr]::Zero)) { Write-Verbose 'clipboard has been successfully opened.' try { if (!(Test-ClipFormat 13)) { throw 'clipboard does not contain any textual data.' } if (($data = $user32.GetClipboardData.Invoke(13)) -eq [IntPtr]::Zero) { throw 'clipboard retrieval failed.' } if (($ptxt = $kernel32.GlobalLock.Invoke($data)) -eq [IntPtr]::Zero) { throw 'locking memory failed.' } [Marshal]::PtrToStringAuto($ptxt) } catch { Write-Verbose $_ } finally { if ($ptxt) { if (!$kernel32.GlobalUnlock.Invoke($data)){ Write-Verbose 'unlocking memory failed.' } } } if ($user32.CloseClipboard.Invoke()) { Write-Verbose 'clipboard has has been successfully closed.' } } # success } } Export-ModuleMember -Function Get-Clipboard |