本文介绍 PSScriptAnalyzer 的各种功能以及如何使用它们。
解析器错误
从版本 1.18.0 开始, PSScriptAnalyzer 在输出流中将分析器错误作为诊断记录发出。
Invoke-ScriptAnalyzer -ScriptDefinition '"b" = "b"; function eliminate-file () { }'
RuleName Severity ScriptName Line Message
-------- -------- ---------- ---- -------
InvalidLeftHandSide ParseError 1 The assignment expression isn't
valid. The input to an
assignment operator must be an
object that's able to accept
assignments, such as a variable
or a property.
PSUseApprovedVerbs Warning 1 The cmdlet 'eliminate-file' uses an
unapproved verb.
RuleName 设置为解析器错误的 ErrorId。
若要禁止显示 ParseErrors,请勿将其作为值包含在 Severity 参数中。
$invokeScriptAnalyzerSplat = @{
ScriptDefinition = '"b" = "b"; function eliminate-file () { }'
Severity = 'Warning'
}
Invoke-ScriptAnalyzer @invokeScriptAnalyzerSplat
RuleName Severity ScriptName Line Message
-------- -------- ---------- ---- -------
PSUseApprovedVerbs Warning 1 The cmdlet 'eliminate-file' uses an
unapproved verb.
抑制规则
您可以通过使用 修饰脚本、函数或参数来禁止规则。NET 的 SuppressMessageAttribute。 SuppressMessageAttribute 的构造函数采用两个参数:类别和检查 ID。 将 categoryID 参数设置为要禁止的规则的名称,并将 checkID 参数设置为空或空字符串。 您可以选择添加第三个命名参数,其中包含禁止显示消息的理由:
function SuppressMe()
{
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSProvideCommentHelp', '',
Justification='Just an example')]
param()
Write-Verbose -Message "I'm making a difference!"
}
在您修饰的脚本、函数或参数的范围内,将禁止显示所有规则违规。
若要禁止显示特定参数上的消息,请将 SuppressMessageAttribute 的 CheckId 参数设置为参数的名称:
function SuppressTwoVariables()
{
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSProvideDefaultParameterValue', 'b')]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSProvideDefaultParameterValue', 'a')]
param([string]$a, [int]$b)
{
}
}
使用 SuppressMessageAttribute 的 Scope 属性将规则抑制限制为属性范围内的函数或类。
使用值 Function 来抑制属性范围内所有函数的冲突。 使用值 Class 禁止对属性范围内所有类的冲突:
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSProvideCommentHelp', '', Scope='Function')]
param()
function InternalFunction
{
param()
Write-Verbose -Message "I am invincible!"
}
你可以通过将 SuppressMessageAttribute 的 Target 属性设置为正则表达式或万用符模式,进一步限制基于函数、参数、类、变量或对象名称的抑制。
例如,若要禁止 和 中 start-barstart-baz 规则冲突,但不禁止 和 start-foo中 start-bam :
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingWriteHost', '',
Scope='Function', Target='start-ba[rz]')]
param()
function start-foo {
write-host "start-foo"
}
function start-bar {
write-host "start-bar"
}
function start-baz {
write-host "start-baz"
}
function start-bam {
write-host "start-bam"
}
要禁止所有功能中的违规行为:
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingWriteHost', '',
Scope='Function', Target='*')]
Param()
要抑制 中的start-barstart-baz违规行为,但不start-bam禁止 中的违规start-foo行为:
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingWriteHost', '',
Scope='Function', Target='start-b*')]
Param()
注释
无法使用 SuppressMessageAttribute 抑制分析器错误。
ScriptAnalyzer 中的设置支持
可以创建描述要根据 严重性包含或排除的 ScriptAnalyzer 规则的设置。 使用 的 设置Invoke-ScriptAnalyzer 参数指定配置。
设置参数允许你为特定环境创建自定义配置。
ScriptAnalyzer 支持以下模式来指定设置文件:
内置预设
ScriptAnalyzer 附带了一组内置预设,可用于分析脚本。 例如,如果要在模块上运行 PowerShell 库 规则,请使用以下命令:
Invoke-ScriptAnalyzer -Path /path/to/module/ -Settings PSGallery -Recurse
此外,您还可以使用其他内置预设,包括 DSC 和 CodeFormatting。 这些预设可以针对 “设置 ”参数进行制表符完成。
Explicit
以下示例从默认规则集中排除两个规则,以及严重性不是 “错误” 和 “警告”的任何规则。
# PSScriptAnalyzerSettings.psd1
@{
Severity=@('Error','Warning')
ExcludeRules=@('PSAvoidUsingCmdletAliases', 'PSAvoidUsingWriteHost')
}
然后,您可以使用以下命令调用 Invoke-ScriptAnalyzer该设置文件:
Invoke-ScriptAnalyzer -Path MyScript.ps1 -Settings PSScriptAnalyzerSettings.psd1
下一个示例选择要执行的几个规则,而不是所有默认规则。
# PSScriptAnalyzerSettings.psd1
@{
IncludeRules=@('PSAvoidUsingPlainTextForPassword',
'PSAvoidUsingConvertToSecureStringWithPlainText')
}
然后,您可以调用该设置文件:
Invoke-ScriptAnalyzer -Path MyScript.ps1 -Settings PSScriptAnalyzerSettings.psd1
隐式
如果将名为 PSScriptAnalyzerSettings.psd1 的设置文件放置在项目根目录中,则 PSScriptAnalyzer 会在将项目根目录作为 Path 参数传递时发现该文件。
Invoke-ScriptAnalyzer -Path "C:\path\to\project" -Recurse
明确提供设置优先于这种隐式模式。 你可以在SettingsPSScriptAnalyzer模块的文件夹中找到示例设置文件。
检查 PowerShell 版本兼容性
PSScriptAnalyzer 可以检查 PowerShell 脚本是否与其他 PowerShell 版本和环境不兼容。 PSScriptAnalyzer 包括四个用于检查兼容性问题的规则:
- PSUseCompatibleCmdlet 检查脚本中使用的 cmdlet 是否在其他 PowerShell 环境中可用
- PSUseCompatibleCommands 检查脚本中使用的命令是否在其他 PowerShell 环境中可用
- PSUseCompatibleSyntax 检查脚本中使用的语法是否兼容其他版本的 PowerShell
- PSUseCompatibleTypes 检查 .NET 类型和静态方法或属性是否在其他 PowerShell 环境中可用
有关如何使用这些规则的详细信息,请参阅 PowerShell 团队博客上的使用 PSScriptAnalyzer 检查 PowerShell 版本兼容性 。
自定义规则
可以在设置文件中提供自定义规则的一个或多个路径。 重要的是,这些路径指向模块的文件夹(隐式使用模块清单)或模块的脚本文件 ()。.psm1 模块必须导出 Export-ModuleMember 自定义规则函数,以便它们可供 PSScriptAnalyzer 使用。
在这个例子中, CustomRulePath 属性指向两个不同的模块。 这两个模块都导出带有谓词 Measure 的规则函数,因此 Measure-* 用于属性 IncludeRules。
@{
CustomRulePath = @(
'.\output\RequiredModules\DscResource.AnalyzerRules'
'.\tests\QA\AnalyzerRules\SqlServerDsc.AnalyzerRules.psm1'
)
IncludeRules = @(
'Measure-*'
)
}
还可以通过在 IncludeRules 属性中列出规则来添加默认规则。 在包含默认规则时,请务必将 属性 IncludeDefaultRules 设置为 $true;否则将使用默认规则。
@{
CustomRulePath = @(
'.\output\RequiredModules\DscResource.AnalyzerRules'
'.\tests\QA\AnalyzerRules\SqlServerDsc.AnalyzerRules.psm1'
)
IncludeDefaultRules = $true
IncludeRules = @(
# Default rules
'PSAvoidDefaultValueForMandatoryParameter'
'PSAvoidDefaultValueSwitchParameter'
# Custom rules
'Measure-*'
)
}
在Visual Studio Code中使用自定义规则(VS Code)
你也可以使用VS Code设置文件里提供的自定义规则。 添加一个VS Code工作区设置文件(),.vscode/settings.json内容如下。
{
"powershell.scriptAnalysis.settingsPath": ".vscode/analyzersettings.psd1",
"powershell.scriptAnalysis.enable": true,
}
ScriptAnalyzer 作为 .NET 库
您可以直接将 ScriptAnalyzer 的引擎和功能用作库。
以下是公共接口:
using Microsoft.Windows.PowerShell.ScriptAnalyzer;
public void Initialize(System.Management.Automation.Runspaces.Runspace runspace,
Microsoft.Windows.PowerShell.ScriptAnalyzer.IOutputWriter outputWriter,
[string[] customizedRulePath = null],
[string[] includeRuleNames = null],
[string[] excludeRuleNames = null],
[string[] severity = null],
[bool suppressedOnly = false],
[string profile = null])
public System.Collections.Generic.IEnumerable<DiagnosticRecord> AnalyzePath(string path,
[bool searchRecursively = false])
public System.Collections.Generic.IEnumerable<IRule> GetRule(string[] moduleNames,
string[] ruleNames)
违规纠正
您可以使用 修复 开关自动替换违规内容,使用建议的替代方案。 此外,由于实现了 Invoke-ScriptAnalyzer,因此可以使用 WhatIf 或 Confirm 来找出将应用哪些更正。 应用修正时应使用源码控制,因为某些更改,比如 AvoidUsingPlainTextForPassword,可能需要其他脚本修改,无法自动完成。 当你自动应用建议时,初始编码并不总能保持。
如果你的脚本依赖某种特定的编码,你应该检查文件编码。
错误记录的 SuggestedCorrections 属性使得在 VS Code 等编辑器中实现快速修复场景。 我们为以下规则提供有效的 SuggestedCorrection :
- 避免别名
- 避免使用PlainTextForPassword
- 误导性反引号
- MissingModuleManifestField
- UseToExportFieldsInManifest