Parsing PowerShell scripts
The PsParser class, introduced in Windows PowerShell 2.0, provides a mechanism to parse a script into a collection of tokens. There are some neat applications written using the Tokenize method such as Syntax Highlighting, Alias resolving and discovering functions in scripts . One other great benefit of the method is the ability to find if a script contains syntax errors without actually running the script.
The Tokenize method has two overloads, both accept a script as a string or as an array of lines (Script parameter) and both update a referenced variable with a collection of the errors that occurred when parsing the script (Errors parameter).
Test-PSScript is a v2 advanced function. Its FilePath parameter accepts input from the pipeline or through the command parameter. The output of the function is an extended Token object (see sample usage and result below) which includes the path of the script, Error Message, the line where the error occurred and some other information.
#Requires -Version 2
function Test-PSScript
{
param(
[Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
[ValidateNotNullOrEmpty()]
[Alias('PSPath','FullName')]
[System.String[]] $FilePath,
[Switch]$IncludeSummaryReport
)
begin
{
$total=$fails=0
}
process
{
$FilePath | Foreach-Object {
if(Test-Path -Path $_ -PathType Leaf)
{
$Path = Convert-Path -Path $_
$Errors = $null
$Content = Get-Content -Path $path
$Tokens = [System.Management.Automation.PsParser]::Tokenize($Content,[ref]$Errors)
if($Errors)
{
$fails+=1
$Errors | Foreach-Object {
$_.Token | Add-Member -MemberType NoteProperty -Name Path -Value $Path -PassThru | `
Add-Member -MemberType NoteProperty -Name ErrorMessage -Value $_.Message -PassThru
}
}
$total+=1
}
}
}
end
{
if($IncludeSummaryReport)
{
Write-Host "`n$total script(s) processed, $fails script(s) contain syntax errors."
}
}
}
Sample usage:
PS > Get-ChildItem –Filter *.ps1 | Test-PSScript -IncludeSummaryReport
Path : D:\scripts\Recycle-IIsAppPool.ps1
ErrorMessage : Missing closing ')' in expression.
Content : <position>
Type : Position
Start : 3928
Length : 0
StartLine : 113
StartColumn : 1
EndLine : 113
EndColumn : 1
Path : D:\scripts\Play-Sound.ps1
ErrorMessage : Missing expression after unary operator '--'.
Content : --
Type : Operator
Start : 975
Length : 2
StartLine : 35
StartColumn : 32
EndLine : 35
EndColumn : 34
35 script(s) processed, 2 script(s) contain syntax errors.
For Powershell 1.0 parsing technique see Keith Hill’s Preparsing Scripts to Check for Syntax Errors blog post.