-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Find-Splat.ps1
141 lines (133 loc) · 5.43 KB
/
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
141
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
#>
[Alias('??@','fSplat')]
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!'
}
}