ReflectCmdlet.psm1
function Get-CommandSource { <# .SYNOPSIS Gets command source code. .DESCRIPTION The Get-CommandSource cmdlet finds the source code/implementation for a cmdlet. .PARAMETER Name Specifies the path or name of the command to retrieve the source code. Accepts pipeline input. .PARAMETER Decompiler Specifies which decompiler or source will be used for browsing the source code. .INPUTS System.Management.Automation.CommandInfo System.String You can pipe command names to this cmdlet. .OUTPUTS System.Management.Automation.PSObject .EXAMPLE Get-CommandSource Write-Host .EXAMPLE Get-Command Write-Host | Get-CommandSource -Decompiler ILSpy .LINK https://github.com/aberus/ReflectCmdlet #> [CmdletBinding()] [OutputType([PSObject])] [Alias('gcmso')] param( [Parameter(Position = 0, Mandatory=$true, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)] [ValidateNotNullOrEmpty()] [String]$Name, [Decompiler]$Decompiler ) $commandInfo = if ($_ -is [System.Management.Automation.CommandInfo]) { $_ } else { Get-Command -Name $Name } if ($commandInfo -is [System.Management.Automation.AliasInfo]) { $commandInfo = $commandInfo.ResolvedCommand } if ($commandInfo -is [System.Management.Automation.FunctionInfo]) { $object = New-Object PSObject -Property $([ordered]@{ CommandType = $commandInfo.CommandType Name = $commandInfo.Name Version = $commandInfo.Version Type = $commandInfo.CommandType }) $functionPath = $commandInfo.ScriptBlock.File if ($functionPath) { $object | Add-Member -MemberType NoteProperty -Name Location -Value $functionPath Invoke-Item $functionPath } else { $modulePath = $commandInfo.Module.Path if ($modulePath) { $modulePath = Split-Path -Path $modulePath $object | Add-Member -MemberType NoteProperty -Name Location -Value $modulePath Invoke-Item $modulePath } else { Write-Error "Unable to find this function's file or module location" } } return $object } if ($commandInfo -is [System.Management.Automation.CmdletInfo]) { $assembly = $commandInfo.ImplementingType.Assembly.Location if (!$assembly) { $assembly = $commandInfo.DLL } $type = $commandInfo.ImplementingType.FullName if (($Decompiler -eq [Decompiler]::ILSpy -or !$Decompiler) -and (Get-Command ILSpy -ErrorAction Ignore)) { Start-Process -FilePath ILSpy -ArgumentList "`"$assembly`" /navigateTo:T:$type" } elseif (($Decompiler -eq [Decompiler]::dnSpy -or !$Decompiler) -and (Get-Command dnSpy -ErrorAction Ignore)) { Start-Process -FilePath dnSpy -ArgumentList "`"$assembly`" --select T:$type" } elseif (($Decompiler -eq [Decompiler]::dotPeek -or !$Decompiler) -and (Get-Command dotPeek -ErrorAction Ignore)) { Start-Process -FilePath dotPeek -ArgumentList /select=$assembly!$type } elseif (($Decompiler -eq [Decompiler]::JustDecompile -or !$Decompiler) -and (Get-Command JustDecompile -ErrorAction Ignore)) { Start-Process -FilePath JustDecompile -ArgumentList "/target:`"$assembly`"" } elseif (($Decompiler -eq [Decompiler]::Reflector -or !$Decompiler) -and (Get-Command reflector -ErrorAction Ignore)) { Start-Process -FilePath reflector -ArgumentList "/select:$type `"$assembly`"" } elseif ($Decompiler -eq [Decompiler]::GitHub -or !$Decompiler) { $class = $commandInfo.ImplementingType.Name $uri = "https://api.github.com/search/code?q=`"class+${class}`"+in:file+repo:powershell/powershell" [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 $result = Invoke-RestMethod -Uri $uri -Method Get if ($result) { $url = $result.items | Select-Object -ExpandProperty html_url Start-Process -FilePath $url } } else { throw 'Unable to find decompiler in your path' } $object = New-Object PSObject -Property $([ordered]@{ CommandType = $commandInfo.CommandType Name = $commandInfo.Name Version = $commandInfo.Version Type = $type Location = $assembly }) return $object } } enum Decompiler { dnSpy ILSpy dotPeek JustDecompile Reflector GitHub } |