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

如何阻止PowerShell ValidateSet参数补全器重复建议已选值?

WDAC策略参数补全去重与验证实现方案

问题背景

为Remove-WDACConfig cmdlet的PolicyIDs和PolicyNames参数实现了基于IValidateSetValuesGenerator类的验证与补全,但补全时会重复建议已选中的值,需要在保留验证功能的同时,让补全器只显示未选中的选项。

解决方案

由于IValidateSetValuesGenerator无法访问已输入的参数值,因此采用保留ValidateSet验证+自定义ArgumentCompleter补全的组合方案:通过原有的验证类确保输入合法性,用自定义补全逻辑过滤已选值。

1. 保留验证类(用于ValidateSet验证)

# PolicyNames参数的ValidateSet验证类
Class PolicyNamez : System.Management.Automation.IValidateSetValuesGenerator {
    [string[]] GetValidValues() {
        return ((CiTool -lp -json | ConvertFrom-Json).Policies | Where-Object { $_.IsSystemPolicy -ne "True" }).Friendlyname
    }
}   

# PolicyIDs参数的ValidateSet验证类     
Class PolicyIDz : System.Management.Automation.IValidateSetValuesGenerator {
    [string[]] GetValidValues() {
        return ((CiTool -lp -json | ConvertFrom-Json).Policies | Where-Object { $_.IsSystemPolicy -ne "True" }).policyID
    }
}

2. Cmdlet参数定义(保留原ValidateSet配置)

function Remove-WDACConfig {
    [CmdletBinding(DefaultParameterSetName = "Default")]
    param(
        [Parameter(Mandatory = $true, ParameterSetName = "Remove Policies")]
        [switch]$RemovePolicies,

        [ValidateSet([PolicyIDz])]
        [Parameter(Mandatory = $false, ParameterSetName = "Remove Policies")]
        [string[]]$PolicyIDs,

        [ValidateSet([PolicyNamez])]
        [Parameter(Mandatory = $false, ParameterSetName = "Remove Policies")]
        [string[]]$PolicyNames
    )

    # 此处添加你的cmdlet核心逻辑
}

3. 添加自定义参数补全器(实现去重)

# 为PolicyIDs配置去重补全
Register-ArgumentCompleter -CommandName Remove-WDACConfig -ParameterName PolicyIDs -ScriptBlock {
    param($wordToComplete, $commandAst, $cursorPosition)

    # 解析已输入的PolicyIDs值
    $selectedIDs = $commandAst.FindAll({ 
        $args[0] -is [System.Management.Automation.Language.ParameterAst] -and 
        $args[0].ParameterName -eq 'PolicyIDs' 
    }, $false) | ForEach-Object {
        $_.Arguments.Extent.Text -replace '["'']', '' -split ',' | Where-Object { $_ -match '\S' }
    }

    # 获取所有可用策略ID,过滤已选值
    $allIDs = ((CiTool -lp -json | ConvertFrom-Json).Policies | Where-Object { $_.IsSystemPolicy -ne "True" }).policyID
    $availableIDs = $allIDs | Where-Object { $_ -notin $selectedIDs }

    # 生成补全结果
    $availableIDs | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object {
        [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
    }
}

# 为PolicyNames配置去重补全(兼容带空格的名称)
Register-ArgumentCompleter -CommandName Remove-WDACConfig -ParameterName PolicyNames -ScriptBlock {
    param($wordToComplete, $commandAst, $cursorPosition)

    # 解析已输入的PolicyNames值
    $selectedNames = $commandAst.FindAll({ 
        $args[0] -is [System.Management.Automation.Language.ParameterAst] -and 
        $args[0].ParameterName -eq 'PolicyNames' 
    }, $false) | ForEach-Object {
        $_.Arguments.Extent.Text -replace '["'']', '' -split ',' | Where-Object { $_ -match '\S' }
    }

    # 获取所有可用策略名称,过滤已选值
    $allNames = ((CiTool -lp -json | ConvertFrom-Json).Policies | Where-Object { $_ -isSystemPolicy -ne "True" }).Friendlyname
    $availableNames = $allNames | Where-Object { $_ -notin $selectedNames }

    # 生成带引号的补全结果(处理含空格的名称)
    $availableNames | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object {
        [System.Management.Automation.CompletionResult]::new("`"$_`"", $_, 'ParameterValue', $_)
    }
}

关键说明

  • 验证逻辑保留:原有的ValidateSet验证仍然生效,确保输入的策略ID/名称均为合法值。
  • 补全去重:自定义补全器通过解析命令语法树获取已输入的参数值,过滤后只显示未选中的选项。
  • 兼容特殊名称:策略名称含空格时,补全结果自动添加双引号,避免PowerShell解析错误。
  • 版本适配:支持PowerShell 7.4,利用CommandAst实现参数值解析。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 03:17:05