4

I'm writing a console application to validate the PowerShell script syntax. My request is to validate the PowerShell script without executing the script. I found this below PowerShell command which can perform the syntax check without executing the scripts.

Get-Command -syntax 'D:\powershell\deleteDemoFile.ps1'

However, I found that it does not do a complete syntax check. For example a variable is used in the PowerShell without declaring or their is typos in the (Function, if, ForEach, etc.) such syntax error is not captured by the above command.

Below is the sample code of the PowerShell script file (.\deleteDemoFile.ps1) Notice in the below code the spelling of (if, Function) is wrong and a variable '$log_dir' is used but is not declared.

When I run the PowerShell Command Get-Command -syntax 'D:\powershell\deleteDemoFile.ps1' the command does not throw any syntax error.

Write-Host "Hello, World!"

ifTypo(-not (test-path -path $log_dir )) {
   new-item -itemtype directory -path $log_dir
}


FunctionTypo log {
   Param ([string]$log_string)
   write-host $log_string
   add-content $log_file -value $log_string
}

log("Deleting a demo txt file")

# PowerShell -WhatIf safety parameter
Clear-Host
Get-Childitem D:\powershell\SomeFile\demo.txt -Recurse | Remove-Item

So I was wondering.

  • How efficient is this PowerShell command in order to do a syntax check?
  • Does it only validate the syntax of PowerShell cmdlets, functions, and aliases?
  • Up to which version of PowerShell script this command is compatible?

Is there any other Command which can perform full syntax check?

Here is the reference of the PowerShell command: https://stackoverflow.com/a/55337824/3725706

3
  • 3
    Invoke-ScriptAnalyzer? Commented Jul 15, 2021 at 16:58
  • 1
    Get-Command doesn't validate anything - it only discovers things Commented Jul 15, 2021 at 18:01
  • 1
    @MathiasR.Jessen, true, the purpose of Get-Command -Syntax is to show the syntax diagram (usage information), but to do so the script must be parsed, so as a side effect syntax errors do surface. Commented Jul 16, 2021 at 14:41

3 Answers 3

5

Note that the purpose of Get-Command's -Syntax switch is to show a command's syntax diagram, i.e. to show its parameters and their types, i.e. how to invoke it.

Since discovering this information for scripts requires parsing them, as a side effect you would indeed detect syntax errors[1] (the Get-Command call then fails and reports the specific syntax error encountered).

However, your example script does not contain syntax errors: while it won't do what you want when executed, it is syntactically valid:

  • ifTypo and FunctionTypo are interpreted as command names, not as misspelled keywords.

    • As such, you'd only see the problem on execution, when an attempt to call a command (cmdlet, function, script, alias, executable) named ifTypo, for instance, is made.
  • See the conceptual about_Parsing help topic for information about PowerShell's two fundamental parsing modes, argument mode (like shells) and expression mode (like programming languages).


The Invoke-ScriptAnalyzer cmdlet (part of the PSScriptAnalyzer module you can install with Install-Module PSScriptAnalyzer) suggested by iRon, which is also used in the PowerShell extension for Visual Studio Code for design-time analysis, may be able to point out potential additional problems, but in the case at hand it wouldn't (it only warns against Write-Host use in your script).


Note:

  • PowerShell's two parsing modes invariably amount to a pretty permissive syntax, and in general there's only so much you can do with static analysis in a dynamic language.

  • No existing features can detect the problems with your script; a potential solution is to ask that new rules for flagging potential keyword misspellings be added to Invoke-ScriptAnalyzer, by opening an issue in the project's GitHub repo, but note that such rules are ultimately guesswork, because what looks like a misspelled keyword could be a legitimate command name.


[1] In effect, Get-Command -Syntax is indirectly a convenient shortcut to calling the official PowerShell parser in order to find syntax errors, which requires more effort - see this answer.

Sign up to request clarification or add additional context in comments.

6 Comments

@Azhar, Get-Command -Syntax is the best check you can do, because it uses the official parser behind the scenes - please see the footnote I've just added. Again: Your script is syntactically valid. No existing code can detect the problems with your script, unless you add new rules to Invoke-ScriptAnalyzer that detect potential problems, such as looking for command names that look like misspelled keywords. I've also added a new bottom section to cover this.
Thank you for such a detailed explanation. I liked that due to its parsing nature it helps to do a quick syntax check without adding any new rules. This will pretty much accomplish my task to validate the script.
Can you also help me with till which version of PowerShell this command Get-Command -Syntax is compatible? Will this command work on older versions of PowerShell. I'm on PSVersion 5.1
@Azhar. Yes, it seems to work in older versions too; just verified in v2.
@Azhar, yes, you''ll need to install the respective version. You can install v2 in parallel with 5.1, but not the others.
|
0
-- +goose Up
-- +goose StatementBegin
SELECT 'up SQL query';
CREATE TABLE Pipelines (
    id INTEGER PRIMARY KEY,
    organization TEXT NOT NULL,
    created INTEGER NOT NULL,
    uuid TEXT NOT NULL,
    hash TEXT NOT NULL,
    json TEXT NOT NULL,
    deployed INTEGER DEFAULT FALSE NOT NULL,
    deleted INTEGER DEFAULT FALSE NOT NULL
);
-- +goose StatementEnd

-- +goose Down
-- +goose StatementBegin
SELECT 'down SQL query';
DROP TABLE Pipelines;
-- +goose StatementEnd

2 Comments

As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.
This does not provide an answer to the question. Once you have sufficient reputation you will be able to comment on any post; instead, provide answers that don't require clarification from the asker. - From Review
0

While the accepted answer correctly explains why Get-Command -Syntax and even Invoke-ScriptAnalyzer do not catch logical errors like keyword typos (e.g., ifTypo), the direct answer to "Is there any other Command which can perform full syntax check?" is yes.

The definitive way to perform a pure syntax check is to use PowerShell's own internal parser, available via the .NET class [System.Management.Automation.Language.Parser].

This method will not execute the script, but it will catch any true parsing errors, such as mismatched brackets ({}), incomplete commands, or invalid language constructs.


The Solution: A Reusable Syntax-Checking Function

Here is a simple, reusable PowerShell function that wraps the parser's functionality. You can use this in your console application or any automation pipeline.

<#
.SYNOPSIS
  Validates the syntax of a PowerShell script file without executing it.
.DESCRIPTION
  This function uses the internal .NET Parser class to perform a full syntax
  check on a specified .ps1 file. It does not execute any of the script's logic.
  It returns any parsing errors it finds. If no errors are found, it returns nothing.
.PARAMETER Path
  The path to the PowerShell script file (.ps1) to validate.
.EXAMPLE
  PS C:\> Test-PSScriptSyntax -Path "C:\Scripts\GoodScript.ps1"
  # This command will produce no output if the syntax is valid.

.EXAMPLE
  PS C:\> $errors = Test-PSScriptSyntax -Path "C:\Scripts\BadScript.ps1"
  PS C:\> if ($errors) {
  >>   Write-Warning "Syntax errors were found:"
  >>   $errors | ForEach-Object { $_.Message }
  >> }
  WARNING: Syntax errors were found:
  Missing closing '}' in statement block or type definition.
.OUTPUTS
  System.Management.Automation.Language.ParseError[]
#>

function Test-PSScriptSyntax {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true, Position = 0)]
        [string]$Path
    )

    # Ensure the file exists before trying to parse it.
    if (-not (Test-Path -LiteralPath $Path -PathType Leaf)) {
        throw "File not found: $Path"
    }

    $scriptContent = Get-Content -LiteralPath $Path -Raw
    $errors = $null

    # Use the internal parser to check the script content.
    # The [void] cast suppresses the AST (Abstract Syntax Tree) output,
    # so we only capture the errors.
    [void][System.Management.Automation.Language.Parser]::ParseInput($scriptContent, [ref]$null, [ref]$errors)

    # Return the collection of errors. If there are no errors, this returns nothing.
    return $errors
}

How to Use This Function

  1. Save the function above into your PowerShell profile or dot-source it in your console application.

  2. Run it against your scripts.

Example with a valid script:

# This will return nothing, indicating success.
Test-PSScriptSyntax -Path 'D:\powershell\validScript.ps1'

Example with a script that has a missing }:

# This will return one or more ParseError objects.
$syntaxErrors = Test-PSScriptSyntax -Path 'D:\powershell\brokenScript.ps1'

if ($syntaxErrors) {
    Write-Host "Found $($syntaxErrors.Count) syntax error(s):"
    $syntaxErrors.Message
}

Output:

Found 1 syntax error(s):
Missing closing '}' in statement block or type definition.

Answering Your Original Questions

With this new understanding, we can answer your specific questions:

  1. How efficient is Get-Command -syntax for a syntax check?

    • It is not efficient or reliable. Its purpose is to show a command's parameters, and it only performs a surface-level parse. It will not catch most syntax errors.
  2. Does it only validate the syntax of PowerShell cmdlets, functions, and aliases?

    • It doesn't truly "validate" anything. It inspects a script to find its param() block to display the syntax diagram. The parsing it does is a side effect and is very permissive.
  3. Is there any other Command which can perform full syntax check?

    • Yes. The Test-PSScriptSyntax function provided above uses the official Parser class and is the correct way to perform a pure syntax check.

Why Your Original Script Still Passes a Syntax Check

It's crucial to understand that your original script with ifTypo and FunctionTypo is syntactically valid according to the PowerShell language rules.

  • ifTypo(...) is parsed as a call to a command named ifTypo.

  • FunctionTypo log { ... } is parsed as a call to a command named FunctionTypo with the arguments log and a script block {...}.

This is a runtime error (command not found), not a parse-time syntax error.

To catch these kinds of issues, you need different tools:

  • For Undeclared Variables ($log_dir): The best practice is to put Set-StrictMode -Version Latest at the top of your scripts. This will cause the script to fail at runtime if it tries to use an undeclared variable.

  • For Typos and Best Practices: As others have mentioned, Invoke-ScriptAnalyzer is the tool for this. It is a "linter" that goes beyond basic syntax to find potential bugs, style issues, and common problems. It is the engine used by VS Code to provide real-time feedback.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.