Skip to content

Instantly share code, notes, and snippets.

@trackd
Last active August 16, 2024 22:58
Show Gist options
  • Save trackd/86bf278e99a06231b095462e812326da to your computer and use it in GitHub Desktop.
Save trackd/86bf278e99a06231b095462e812326da to your computer and use it in GitHub Desktop.
function Show-Pipeline {
<#
.SYNOPSIS
Returns an object with the command and resolved command in a pipeline or input line.
@trackd
.PARAMETER Line
the line to parse
.EXAMPLE
$a = gci | % fullname | gi | Show-Pipeline -Verbose
$a | % fullname | gi | Show-Pipeline -Verbose -all
.EXAMPLE
could be used to track down the source of a command in a pipeline from a function
Show-Pipeline -Line $MyInvocation.Line
.EXAMPLE
Show-Pipeline -line 'gci -recurse | gi | select -Last 1 | NotAnActualcmd -param stuff -t v'
.EXAMPLE
Show-Pipeline -line '$stevejobs = gci .\apple -recurse | gi | select -first 1' -Verbose
#>
[cmdletbinding()]
param(
[Parameter(Position = 0)]
[string] $Line,
[Parameter(ValueFromPipeline)]
[object] $InputObject
)
Write-Verbose "Command: $($MyInvocation.MyCommand.Name) Param: $($PSBoundParameters.GetEnumerator())"
if ($MyInvocation.ExpectingInput) {
if ($PSVersionTable.PSVersion -lt [version]'7.4') {
<#
# alt from sudo repo from jaykul/IISResetMe
$cmdline = [System.Management.Automation.InvocationInfo].GetMember(
'_scriptPosition',
[System.Reflection.BindingFlags]'NonPublic,Instance'
)[0].GetValue($MyInvocation).Text
#>
$cmdline = $MyInvocation.GetType().
GetProperty('ScriptPosition', [System.Reflection.BindingFlags] 'Instance, NonPublic').
GetValue($MyInvocation).
Text
}
else {
$cmdline = $MyInvocation.Statement
}
}
else {
$cmdline = $Line
}
if (-Not $cmdline) {
return
}
Write-Verbose $cmdline
$ast = ([System.Management.Automation.Language.Parser]::ParseInput($cmdline, [ref]$null, [ref]$null)).EndBlock.Statements[0]
if ($ast.left) {
# when the pipeline is started by a variable assignment.
Write-Verbose "Pipeline 0 : $($ast.left.extent.text)"
$pipelineElements = $ast.right.PipelineElements
[PSCustomObject]@{
Pipeline = 0
Command = $ast.left.extent.text
Resolved = $ast.operator
params = $ast.right.extent.text
}
}
else {
$pipelineElements = $ast.PipelineElements
}
$i = 1
foreach ($pipeline in $pipelineElements) {
if ($pipeline.commandElements) {
$piped = $pipeline.GetCommandName()
Write-Verbose "Pipeline $i : $piped"
$command = $ExecutionContext.InvokeCommand.GetCommand($piped, 'All')
if (-Not $command) {
$command = "CommandNotFound"
}
elseif ($command.ResolvedCommand) {
Write-Verbose "Resolved alias to $($command.ResolvedCommand.Name)"
$command = $command.ResolvedCommand
}
$param = $pipeline.CommandElements.extent.text -join ' '
}
else {
# when the pipeline is started by a variable.
Write-Verbose "Pipeline $i : $pipeline"
$piped = $command = $pipeline
$param = $pipeline.expression.extent.text
}
[PSCustomObject]@{
Pipeline = $i
Command = $piped
Resolved = $command
params = $param.replace($piped, '').Trim()
}
$i++
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment