使用 PSScriptAnalyzer

本文說明 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 的 SuppressMessageAttributeSuppressMessageAttribute 的建構函式會採用兩個參數:類別和檢查標識碼。 將 categoryID 參數設定為您要隱藏的規則名稱,並將 checkID 參數設定為空值或空字串。 您可以選擇性地新增第三個具名參數,其中包含隱藏訊息的理由:

function SuppressMe()
{
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSProvideCommentHelp', '',
        Justification='Just an example')]
    param()

    Write-Verbose -Message "I'm making a difference!"

}

在您裝飾的指令碼、函數或參數範圍內,會抑制所有規則違規。

若要隱藏特定參數上的訊息,請將 SuppressMessageAttributeCheckId 參數設定為參數的名稱:

function SuppressTwoVariables()
{
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSProvideDefaultParameterValue', 'b')]
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSProvideDefaultParameterValue', 'a')]
    param([string]$a, [int]$b)
    {
    }
}

使用 SuppressMessageAttributeScope 屬性,將規則隱藏限制為屬性範圍內的函式或類別。

使用值 Function 來隱藏屬性範圍內所有函式的違規。 使用值 Class 來隱藏屬性範圍內所有類別的違規:

[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSProvideCommentHelp', '', Scope='Function')]
param()

function InternalFunction
{
    param()

    Write-Verbose -Message "I am invincible!"
}

你還可以透過將 SuppressMessageAttributeTarget 屬性設為正則表達式或萬用字元模式,進一步限制基於函式、參數、類別、變數或物件名稱的抑制。

例如,若要隱藏 和 start-bar 規則違規,但不是 和 start-bazstart-foostart-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-bar抑制 中的start-bazstart-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

此外,您還可以使用其他內建預設,包括 DSCCodeFormatting。 這些預設集可以針對 「設定 」參數完成標籤。

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的設定檔案放在專案根目錄中,當您將專案根目錄作為 Path 參數傳遞時,PSScriptAnalyzer 會探索它。

Invoke-ScriptAnalyzer -Path "C:\path\to\project" -Recurse

明確提供設定優先權高於此隱含模式。 你可以在 SettingsPSScriptAnalyzer 模組的資料夾中找到範例設定檔案。

檢查 PowerShell 版本相容性

PSScriptAnalyzer 可以檢查 PowerShell 腳本是否與其他 PowerShell 版本和環境不相容。 PSScriptAnalyzer 包含四個規則來檢查相容性問題:

如需如何使用這些規則的詳細資訊,請參閱 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,您可以使用 WhatIfConfirm 來找出要套用哪些更正。 你在套用修正時應該使用原始碼控制,因為有些變更,例如 AvoidUsingPlainTextForPassword,可能需要其他無法自動完成的腳本修改。 當你自動套用建議時,初始編碼並不一定能被保留。 如果你的腳本依賴特定編碼,你應該檢查檔案編碼。

錯誤紀錄的 SuggestedCorrections 屬性使得像 VS Code 這類編輯器能快速修正。 我們為下列規則提供有效的 SuggestedCorrection

  • 避免別名
  • 避免使用PlainTextForPassword
  • 誤導性反引號
  • MissingModuleManifestField
  • UseToExportFieldsInManifest