如何使用 PowerShell cmdlet 对 PowerShell 脚本文件进行完整的语法检查

问题描述

我正在编写一个控制台应用程序来验证 PowerShell 脚本语法。 我的请求是在不执行脚本的情况下验证 PowerShell 脚本。我在 PowerShell 命令下面发现了这个,它可以在不执行脚本的情况下执行语法检查。

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

但是,我发现它没有做完整的语法检查。 例如,在 PowerShell 中使用了一个变量而不声明 或者他们在 (Function,if,ForEach 等) 中有错别字 上面的命令没有捕获这样的语法错误

下面是PowerShell脚本文件(.\deleteDemoFile.ps1)的示例代码 请注意以下代码中 (if,Function) 的拼写错误,并且使用了变量“$log_dir”但未声明。

当我运行 PowerShell 命令 Get-Command -Syntax 'D:\powershell\deleteDemoFile.ps1' 时,该命令不会引发任何语法错误

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

所以我想知道。

  • 此 PowerShell 命令进行语法检查的效率如何?
  • 它是否只验证 PowerShell cmdlet、函数和别名的语法?
  • 此命令最多兼容哪个版本的 PowerShell 脚本?

是否还有其他可以执行完整语法检查的命令?

这里是PowerShell命令的参考:https://stackoverflow.com/a/55337824/3725706

解决方法

注意Get-Command-Syntax开关的目的是显示命令的syntax diagram,即显示其参数及其类型,即如何调用它.

因为发现脚本的这些信息需要解析它们,作为副作用,您确实会检测语法错误[1] (然后 Get-Command 调用失败并报告遇到的特定语法错误)。

然而,您的示例脚本包含语法错误:虽然它在执行时不会做您想要的 /em>,它在语法上有效

  • ifTypoFunctionTypo 被解释为命令名称,而不是拼错的关键字

    • 因此,您只会在执行时看到问题,当尝试调用名为 {例如,{1}} 是制作的。
  • 有关 PowerShell 的两种基本解析模式,参数 模式(如 shell)和 表达式 的信息,请参阅概念性的 about_Parsing 帮助主题模式(如编程语言)


Invoke-ScriptAnalyzer 建议的 iRon cmdlet(您可以使用 ifTypo 安装的 PSScriptAnalyzer 模块的一部分),它也用于 Visual Studio Code 的 PowerShell 扩展对于设计时分析,可能能够指出潜在额外的问题,但在手头的情况下它不会(它只警告Install-Module PSScriptAnalyzer在您的脚本中使用)。


注意:

  • PowerShell 的两种解析模式总是等同于一种非常宽松的 语法,并且一般来说,您可以使用动态语言中的静态 分析做很多事情。

  • 现有功能无法检测您的脚本问题;一个潜在的解决方案是要求将标记潜在关键字拼写错误的新规则添加到 opening an issue in the project's GitHub repo 中的 Write-Host,但请注意,此类规则是最终猜测,因为看起来拼错的关键字可能是合法的命令名称。


[1] 实际上,Invoke-ScriptAnalyzer 是间接调用官方 PowerShell 解析器以查找语法错误的便捷快捷方式,这需要更多的努力 - 参见 this answer

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...