Find-Splat.ps1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
function Find-Splat { <# .Synopsis Finds commands that can be splatted to given an input. .Description Finds the commands whose input parameters match an input object, and returns an [ordered] dictionary of parameters. .Link Get-Splat .Link Use-Splat .Example @{Id=$pid} | Find-Splat -Global #> param( # One or more commands. # If not provided, commands from the current module will be searched. # If there is no current module, all commands will be searched. [Parameter(Position=0)] [string[]]$Command, # The splat [Parameter(ValueFromPipeline=$true,Position=1)] [Alias('InputObject')] [PSObject]$Splat, # If set, will look for all commands, even if Find-Splat is used within a module. [Alias('G')][switch]$Global, # If set, will look for commands within the current module. # To make this work within your own module Install-Splat. [Alias('L')][switch]$Local, # If provided, will look for commands within any number of loaded modules. [Alias('M')][string[]]$Module, # If set, will return regardless of if parameters map, are valid, and have enough mandatory parameters [switch]$Force) begin { $myModule = $MyInvocation.MyCommand.ScriptBlock.Module $cmdTypes = 'Function,Cmdlet,ExternalScript,Alias' $resolveAliases = { begin { $n = 0 } process { $n++ if ($t -is [int] -and $id) { $p = $n* 100 / $t Write-Progress "Resolving" "$_ " -PercentComplete $p -Id $id } if ($_.ResolvedCommand) { $_.ResolvedCommand } else { $_ } } end { Write-Progress 'Resolving Aliases' 'Complete' -Id $id } } $filterCmds = { process { foreach ($c in $Command) { if ($_ -like $c) { return $_ } } } } } process { if (-not $Splat) { return } $id =[Random]::new().Next() $commandList = @(if (-not $Command) { Write-Progress -Id $id -Activity 'Getting Commands' -Status ' ' if ($MyModule -and $Local) { $myModule.ExportedCommands.Values | . $resolveAliases | Select-Object -Unique } elseif ($module) { foreach ($m in $Module) { $rm = Get-Module $m if (-not $rm) { continue } $rm.ExportedCommands.Values | . $resolveAliases | Select-Object -Unique } } else { $allcmds = @($ExecutionContext.SessionState.InvokeCommand.GetCommands('*',$cmdTypes, $true)) $t = $allcmds.Count $allcmds |. $resolveAliases | Select-Object -Unique } } elseif ($module) { foreach ($m in $Module) { $rm = Get-Module $m if (-not $rm) { continue } $rm.ExportedCommands.Values | . $resolveAliases | . $filterCmds | Select-Object -Unique } } elseif ($Global) { foreach ($c in $Command) { $ExecutionContext.SessionState.InvokeCommand.GetCommands($c,$cmdTypes, $true) } } elseif ($MyModule -and $Local) { $myModule.ExportedCommands.Values | . $filterCmds | . $resolveAliases | Select-Object -Unique } else { foreach ($cmd in $Command) { if ($cmd -is [string] -and $cmd.Contains('*')) { $ExecutionContext.SessionState.InvokeCommand.GetCommands($cmd,$cmdTypes, $true) } else { $cmd } } }) $psBoundParameters.Command = $commandList if ($Splat -is [Collections.IDictionary]) { $Splat = if ($splat.GetType().Name -ne 'PSBoundParametersDictionary') { [PSCustomObject]$Splat } else { [PSCustomObject]([Ordered]@{} + $Splat) } } $c,$t= 0, $commandList.Count foreach ($cmd in $commandList) { if ($t -gt 1) { $c++;$p=$c*100/$t Write-Progress -Id $id -Activity 'Finding Splats' -Status "$cmd " -PercentComplete $p } $Splat | & ${?@} $cmd -Force:$Force | Select-Object -Property * -ExcludeProperty SyncRoot,IsSynchronized,IsReadOnly,IsFixedSize,Count | & { process { if ($_.PercentFit -eq 0) { return } $_.pstypenames.clear() $_.pstypenames.add('Find.Splat.Output') $keys, $values = @($_.Keys), @($_.Values) $resplat = [Ordered]@{} for ($i=0;$i -lt $keys.count;$i++) { $resplat[$keys[$i]] = $values[$i] } $_.psobject.properties.remove('Keys') $_.psobject.properties.remove('Values') $_.psobject.properties.Add([Management.Automation.PSNoteProperty]::new('Splat', $resplat)) $_ } } } Write-Progress -Id $id -Completed -Activity 'Finding Splats' -Status 'Complete!' } } |