-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Use-Splat.ps1
140 lines (127 loc) · 4.68 KB
/
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
140
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
#>
[Alias('.@','uSplat')]
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)]
[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() }
}
}
}