Use-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 |
function Use-Splat { <# .Synopsis Uses a splat. .Description Uses a splat to call a command. If passed from Find-Splat,Get-Splat or Test-Splat, the command will be automatically detected. If called as .@, this will run only provided commands If called as *@, this will run any found commands .Link Get-Splat .Link Find-Splat .Link Test-Splat .Example @{id=$pid} | Use-Splat gps # When calling Use-Splat is globally imported .Example @{id=$pid} | & ${.@} gps # When calling Use-Splat is nested .Example @{LogName='System';InstanceId=43,44}, @{LogName='Application';InstanceId=10000,10005} | .@ Get-EventLog # get a bunch of different log events #> param( # One or more commands [Parameter(Position=0)] [PSObject[]] $Command, # Any additional positional arguments that would be passed to the command [Parameter(Position=1,ValueFromRemainingArguments=$true)] [PSObject[]] $ArgumentList = @(), # The splat [Parameter(ValueFromPipeline=$true)] [PSObject[]] $Splat, # If set, will run regardless of if parameters map, are valid, and have enough mandatory parameters. [switch] $Force, # If set, will run the best fit out of multiple commands. # The best fit is the command that will use the most of the input splat. [Alias('BestFit','BestFitFunction', 'BF','BFF')] [switch] $Best, # If set, will stream input into a single pipeline of each command. # The non-pipeable parameters of the first input splat will be used to start the pipeline. # By default, a command will be run once per input splat. [Alias('Pipe')] [switch] $Stream) begin { $pipelines = @{} } process { $WeTrustTheSplat = $false if (-not $Command -and $splat.Length -eq 1 -and $splat[0] -is [Collections.IDictionary] -and $Splat[0].psobject.Properties['Command']) { $Command = $Splat[0].psobject.Properties['Command'].Value $WeTrustTheSplat = $true } elseif (-not $command -and $_ -is [PSObject] -and $_.Command -and $_.Splat) { $WeTrustTheSplat = $true $splat = $_.Splat $command = $_.Command } if ($Best -and $command.Count) { $command = $splat | & ${?@} -Command $command | Sort-Object PercentFit -Descending | Select-Object -ExpandProperty Command -First 1 } if (-not $Command) { Write-Error -Message "No command found" -Category ObjectNotFound -ErrorId 'Use-Splat.CommandNotFound' ;return } #region UseTheSplat foreach ($cmd in $Command) { if ($WeTrustTheSplat) { if ($cmd -is [Management.Automation.CommandInfo] -or $cmd -is [ScriptBlock]) { foreach ($s in $splat) { if ($argumentList) { & $cmd @s @ArgumentList } else { & $cmd @s } } } } else { $Splat | & ${?@} $cmd -Force:$Force | & { process { $i = $_ $np = $i.NonPipelineParameter $c = $_.psobject.properties['Command'].Value if ($Stream) { if (-not $pipelines[$c]) { $stepScript = if ($argumentList) { {& $c @np @argumentList} } else { {& $c @np} } $stepPipeline = $stepScript.GetSteppablePipeline() $pipelines[$c] = $stepPipeline $stepPipeline.Begin($true) } else { $stepPipeline = $pipelines[$c] } $stepPipeline.Process([PSCustomObject]$i.PipelineParameter) return } if ($c -is [Management.Automation.CommandInfo] -or $c -is [ScriptBlock]) { if ($ArgumentList) { & $c @i @ArgumentList } else { & $c @i } } }} } } #endregion UseTheSplat } end { if ($pipelines.Count) { foreach ($v in $pipelines.Values) { $v.End() } } } } |