How can I automatically syntax check a powershell script file?
Asked Answered
B

3

16

I want to write a unit-test for some code which generates a powershell script and then check that the script has valid syntax.

What's a good way to do this without actually executing the script?

A .NET code solution is ideal, but a command line solution that I could use by launching an external process would be good enough.

Bordiuk answered 4/4, 2017 at 17:13 Comment(1)
C
15

You could run your code through the Parser and observe if it raises any errors:

# Empty collection for errors
$Errors = @()

# Define input script
$inputScript = 'Do-Something -Param 1,2,3,'

[void][System.Management.Automation.Language.Parser]::ParseInput($inputScript,[ref]$null,[ref]$Errors)

if($Errors.Count -gt 0){
    Write-Warning 'Errors found'
}

This could easily be turned into a simple function:

function Test-Syntax
{
    [CmdletBinding(DefaultParameterSetName='File')]
    param(
        [Parameter(Mandatory=$true, ParameterSetName='File', Position = 0)]
        [string]$Path, 

        [Parameter(Mandatory=$true, ParameterSetName='String', Position = 0)]
        [string]$Code
    )

    $Errors = @()
    if($PSCmdlet.ParameterSetName -eq 'String'){
        [void][System.Management.Automation.Language.Parser]::ParseInput($Code,[ref]$null,[ref]$Errors)
    } else {
        [void][System.Management.Automation.Language.Parser]::ParseFile($Path,[ref]$null,[ref]$Errors)
    }

    return [bool]($Errors.Count -lt 1)
}

Then use like:

if(Test-Syntax C:\path\to\script.ps1){
    Write-Host 'Script looks good!'
}
Cq answered 4/4, 2017 at 17:44 Comment(3)
This is likely the most direct on-point answer to the question. Mine is more general unit testing.Lind
If someone could make this answer a bit more dummy proof, I'd appreciate it. Do I understand correctly that the first and the second code are redundant? Or rather: it's the second one I'm supposed to use?Saccharify
Could it be that to use the function, you need the -path option? For me only Test-Syntax -path C:\path\to\script.ps1 seems to work, not Test-Syntax C:\path\to\script.ps1Saccharify
H
29

I stumbled onto Get-Command -syntax 'script.ps1' and found it concise and useful.

ETA from the comment below: This gives a detailed syntax error report, if any; otherwise it shows the calling syntax (parameter list) of the script.

Humpbacked answered 25/3, 2019 at 12:29 Comment(5)
For me, this just produces the name of the scriupt file.Saccharify
Indeed it does. Now try it on a script that has syntax errors.Humpbacked
This gives a detailed syntax error report, if any; otherwise it shows the calling syntax (parameter list) of the script. This is much easier to use for a quick error check than the accepted answer.Cousin
@royappa: This answer is only useful because of your comment, which has 10 times more information than the answer. +1 for both.Xiphoid
This is just entirely awesome.Homocyclic
C
15

You could run your code through the Parser and observe if it raises any errors:

# Empty collection for errors
$Errors = @()

# Define input script
$inputScript = 'Do-Something -Param 1,2,3,'

[void][System.Management.Automation.Language.Parser]::ParseInput($inputScript,[ref]$null,[ref]$Errors)

if($Errors.Count -gt 0){
    Write-Warning 'Errors found'
}

This could easily be turned into a simple function:

function Test-Syntax
{
    [CmdletBinding(DefaultParameterSetName='File')]
    param(
        [Parameter(Mandatory=$true, ParameterSetName='File', Position = 0)]
        [string]$Path, 

        [Parameter(Mandatory=$true, ParameterSetName='String', Position = 0)]
        [string]$Code
    )

    $Errors = @()
    if($PSCmdlet.ParameterSetName -eq 'String'){
        [void][System.Management.Automation.Language.Parser]::ParseInput($Code,[ref]$null,[ref]$Errors)
    } else {
        [void][System.Management.Automation.Language.Parser]::ParseFile($Path,[ref]$null,[ref]$Errors)
    }

    return [bool]($Errors.Count -lt 1)
}

Then use like:

if(Test-Syntax C:\path\to\script.ps1){
    Write-Host 'Script looks good!'
}
Cq answered 4/4, 2017 at 17:44 Comment(3)
This is likely the most direct on-point answer to the question. Mine is more general unit testing.Lind
If someone could make this answer a bit more dummy proof, I'd appreciate it. Do I understand correctly that the first and the second code are redundant? Or rather: it's the second one I'm supposed to use?Saccharify
Could it be that to use the function, you need the -path option? For me only Test-Syntax -path C:\path\to\script.ps1 seems to work, not Test-Syntax C:\path\to\script.ps1Saccharify
L
5

PS Script Analyzer is a good place to start at static analysis of your code.

PSScriptAnalyzer provides script analysis and checks for potential code defects in the scripts by applying a group of built-in or customized rules on the scripts being analyzed.

It also integrates with Visual Studio Code.

There are a number of strategies for mocking PowerShell as part of unit tests, and also have a look at Pester.

The Scripting Guy's Unit Testing PowerShell Code With Pester
PowerShellMagazine's Get Started With Pester (PowerShell unit testing framework)

Lind answered 4/4, 2017 at 17:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.