You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在PSScriptAnalyzer自定义PowerShell规则中获取脚本文件名?

为PSScriptAnalyzer自定义规则传入目标脚本文件名的方法

问题背景

环境要求脚本仅使用ASCII编码,禁止任何Unicode字符,因此需要创建一个与PSScriptAnalyzer原生UseBOMForUnicodeEncodedFile规则作用相反的自定义PowerShell规则,用于检测脚本文件是否存在字节顺序标记(BOM)。

但根据PSScriptAnalyzer自定义规则文档要求,每个规则函数必须包含Token数组或Ast参数,而检测BOM需要获取目标脚本的文件名。原生UseBOMForUnicodeEncodedFile.cs规则虽实现了此功能,但缺乏C#知识无法转换为PowerShell代码,已编写的部分规则代码无法正确传入文件名。

解决方案

PSScriptAnalyzer的自定义规则函数可以通过[System.Management.Automation.Language.ScriptBlockAst]类型的参数,从Ast对象的Extent.File属性中获取目标脚本的完整路径。无需单独定义$FileName参数,只需将规则函数的参数替换为Ast参数,再从Ast中提取文件名即可。

修正后的完整规则代码

#Requires -Version 3.0

function Measure-AvoidByteOrderMark {
<#
    .SYNOPSIS
    检测脚本文件是否包含字节顺序标记(BOM)
    .DESCRIPTION
    当脚本文件存在BOM时触发警告,符合ASCII编码无BOM的环境要求
    .INPUTS
    [System.Management.Automation.Language.ScriptBlockAst]
    .OUTPUTS
    [Microsoft.Windows.PowerShell.ScriptAnalyzer.Generic.DiagnosticRecord]
#>

    [CmdletBinding()]
    [OutputType([Microsoft.Windows.PowerShell.ScriptAnalyzer.Generic.DiagnosticRecord])]
    Param (
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [System.Management.Automation.Language.ScriptBlockAst]$Ast
    )

    Begin {
        Function Get-Encoding {
            param([Parameter(ValueFromPipeline=$True)] $Path)
            process {
                $Reader = [System.IO.StreamReader]::new($Path, [System.Text.Encoding]::GetEncoding('ISO-8859-1'), $True)
                [Void]$Reader.Peek()
                $encoding = $Reader.CurrentEncoding
                $Reader.Close()
                return $encoding
            }
        }
    }

    Process {
        $FileName = $Ast.Extent.File
        if (-not $FileName) { return }
        
        $Encoding = Get-Encoding $FileName
        $ByteOrderMark = $Encoding.GetPreamble()
        
        # 检测是否存在BOM(非空字节数组即为存在BOM)
        if ($ByteOrderMark.Count -gt 0) {
            # 创建脚本位置信息,定位到文件开头(BOM所在位置)
            $StartPosition = [System.Management.Automation.Language.ScriptPosition]::new(
                $FileName, 1, 1, $Encoding.HeaderName
            )
            $EndPosition = [System.Management.Automation.Language.ScriptPosition]::new(
                $FileName, 1, $ByteOrderMark.Count + 1, $Encoding.HeaderName
            )
            $Extent = [System.Management.Automation.Language.ScriptExtent]::new($StartPosition, $EndPosition)
            
            [Microsoft.Windows.PowerShell.ScriptAnalyzer.Generic.DiagnosticRecord]@{
                Message              = "文件 $FileName 包含 $($Encoding.HeaderName) 字节顺序标记(BOM),不符合ASCII编码要求。"
                Extent               = $Extent
                RuleName             = 'AvoidByteOrderMark'
                Severity             = 'Warning'
                RuleSuppressionID    = $Encoding.HeaderName
            }
        }
    }
}
Export-ModuleMember -Function Measure-*

关键修改说明

  1. 参数替换:将原$FileName参数替换为$Ast(ScriptBlockAst类型),符合PSScriptAnalyzer规则要求。
  2. 获取文件名:通过$Ast.Extent.File提取目标脚本的完整路径。
  3. BOM检测逻辑:直接判断GetPreamble()返回的字节数组长度,非空则表示存在BOM,无需依赖编码器回退类型判断。
  4. 位置信息修正:创建ScriptPosition时传入正确的文件名,定位BOM所在的文件起始位置,确保诊断记录的位置准确。

内容的提问来源于stack exchange,提问作者iRon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 03:15:24