#REQUIRES -VERSION 2.0 #TO DO: # better parsing for function keyword so it only finds actual functions and # not the word in a comment # detect nested filtering functions that use Filter instead of function # better handling of v2 comment blocks # display parameters for nested functions # figure out what to do if external files are dot sourced. Should they be scanned? # Perhaps at least identified. # How do I handle snapins or modules that might get added during script execution but # aren't loaded when I gather the list of possible commands? <# .Synopsis This script will analyze a PowerShell script and create a script profile. .Description This script analyze a given Powershell script and prepare a script profile. Within this profile you will see what parameters are called in the analyzed script, where they are called, what PowerShell commands are executed, what functions are defined internally and if the script is digitally signed. The output is written to the pipeline as a document so that you can save it to a file for review. If you use the -code parameter, the scripts contents will be included in the script profile. If the analyzed script calls another script, references another script via dot sourcing, or loads additional modules and snapins those references will NOT be analyzed, although you should see the lines of code in the script profile so that you can analyze and review further. .Parameter Script The path to the .ps1 script file you want to profile. .Parameter Code If specified, then the script's code will be displayed at the end of the profile. .Example PS C:\> c:\scripts\get-scriptprofile foo.ps1 | Out-file FooProfile.txt Save the basic script profile to a text file. .Example PS C:\> c:\scripts\get-scriptprofile foo.ps1 -code Display the script profile along with the code from foo.ps1 .Example PS C:\scripts> dir test*.ps1 | .\get-scriptprofile.ps1 Build a script profile for every PowerShell script that begins with Test. .Inputs Accepts strings as pipelined input .Outputs [object] .Link Get-Command Get-AuthenticodeSignature About_Functions About_Parameters About_Scripts .Notes NAME: Get-ScriptProfile.ps1 VERSION: 1.2 AUTHOR: Jeffery Hicks http://jdhitsolutions.com/blog LASTEDIT: 1/14/2010 THIS IS A WORK IN PROGRESS...ESPECIALLY WITH POWERSHELL V2.0 SCRIPTS DISCLAIMER AND WARNING: THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. TEST THOROUGHLY IN A NON-PRODUCTION ENVIRONMENT. IF YOU DON'T KNOW WHAT THIS SCRIPT WILL DO...DO NOT RUN IT! Microsoft PowerShell Source File -- Created with SAPIEN Technologies PrimalScript 2009 #> [CmdletBinding()] #define the parameters Param ( [Parameter( ValueFromPipeline=$True, Position=0, Mandatory=$True, HelpMessage="Enter a the path and name to a PowerShell script")] [String[]]$script, [Parameter( Mandatory=$False, HelpMessage="Specify if you want to see the script's code.")] [switch]$code ) Begin { $ErrorActionPreference="SilentlyContinue" #get command information for all current aliaes, functions, filters,cmdlets #and external scripts $cmdHash=@{} Get-Command -CommandType Alias,Function,Filter,ExternalScript,Cmdlet | foreach { $cmdHash.add($_.name,$_.CommandType) } #define some variables $Activity="Script Profiling" } #end Begin Scriptblock Process { If (-Not (Test-Path $script)) { Write-Warning "Cannot find $script." return } $fullname=(Get-Item $script).Fullname Write-Progress -Activity $Activity -Status "Analyzing $script" -CurrentOperation "Testing Signature" -PercentComplete 10 write `n write $fullname.ToUpper() write ("Digital Signature: {0}" -f (Get-AuthenticodeSignature $script).status) Write-Progress -Activity $Activity -Status "Analyzing $script" -CurrentOperation "Parsing content" -PercentComplete 20 $data=Get-Command $fullname $content=($data.scriptContents).Split("`n") #get any requires Write-Progress -Activity $Activity -Status "Analyzing $script" -CurrentOperation "Checking for requirements" -PercentComplete 30 write `n write "`nRequires" write "--------" $content | where {$_.ToLower() -match "requires -"} | foreach { #parse the requirement and get everything to the left of the first dash $_.Substring($_.IndexOf("-")+1).ToLower() } |select -unique #strip out commented lines $content=$content | where {$_ -notmatch "^\s*#"} Write-Progress -Activity $Activity -Status "Analyzing $script" -CurrentOperation "Parsing Parameters" -PercentComplete 45 write "`nParameters" write "----------" $params=@() $data.parameters.values | foreach { $params+=$_.name $_ | select Name,ParameterType } write "`nParameter usage" write "---------------" $content | foreach { $line=$_ $params | foreach { if ($_ -eq "?") { $key="\$_" [regex]$r="$key" } else { $key="$_" [regex]$r="\b$key\b" } if ($line -match $r) { write $line.Trim() } #end if } #end foreach param #select only unique lines to weed out #multiple matches for the same line } | select -Unique #end foreach line Write-Progress -Activity $Activity -Status "Analyzing $script" -CurrentOperation "Parsing defined functions" -PercentComplete 60 write "`nInternally Defined Functions" write "----------------------------" $content | foreach { if ($_ -match "function \w*.\w*") {$matches.values} } Write-Progress -Activity $Activity -Status "Analyzing $script" -CurrentOperation "Parsing commands" -PercentComplete 75 write "`nInvoked Commands" write "----------------" $content | foreach { $line=$_ $cmdHash.keys | foreach { #escape the ? which is a special regex character if ($_ -eq "?") { $key="\$_" [regex]$r="$key" } else { $key="$_" [regex]$r="\b$key\b" } if ($line -match $r) { write $line.Trim() } #end if } #end foreach key } | select -unique #end foreach content line If ($code) { Write-Progress -Activity $Activity -Status "Analyzing $script" -CurrentOperation "Getting script contents" -PercentComplete 90 #write script contents if -code was specified write "`nScript Contents" write "---------------" write $data.scriptcontents } } #end Process script block End { Write-Progress -Activity $Activity -Status "Done!" -CurrentOperation "Finished" -Completed -PercentComplete 100 } #end End script block #end of script