PowerShell 如何用dynamicparam实现runType为download时token必填
PowerShell 动态参数实现方案
实现效果
改造后完全满足需求,且比手写判断的体验更好:
- 仅当
runType传入download时,token参数才会被注册为位置2的必填项,未传时PowerShell会在参数输入阶段直接拦截,不进入脚本主逻辑 - 当
runType传入update时,token参数直接不注册,用户手动传这个参数会收到“参数不存在”的报错,从根源上避免无效参数传入 - 保留原有的
ValidateSet、ValidateNotNullOrEmpty校验规则,不改动原有业务逻辑
改造后完整脚本
[CmdletBinding()] param ( [Parameter(Position=1, Mandatory=$true)] [ValidateSet('download', 'update')] [string]$runType ) # 动态参数定义块 dynamicparam { # 仅当runType为download时,才定义token参数 if ($PSBoundParameters['runType'] -eq 'download') { # 初始化动态参数字典 $paramDict = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary # 初始化参数特性集合 $attrCollection = New-Object System.Collections.ObjectModel.Collection[System.Attribute] # 定义基础参数特性:位置2、必填 $paramAttr = New-Object System.Management.Automation.ParameterAttribute $paramAttr.Position = 2 $paramAttr.Mandatory = $true $attrCollection.Add($paramAttr) # 加入非空校验特性,和原脚本的ValidateNotNullOrEmpty保持一致 $validateAttr = New-Object System.Management.Automation.ValidateNotNullOrEmptyAttribute $attrCollection.Add($validateAttr) # 定义token参数对象(兼容PS5.1/PS7版本的写法) $tokenParam = New-Object -TypeName System.Management.Automation.RuntimeDefinedParameter -ArgumentList @( 'token', [string], $attrCollection ) $paramDict.Add('token', $tokenParam) return $paramDict } } # 手动获取动态参数的值(动态参数不会自动生成同名变量) $token = $PSBoundParameters['token'] # ------------------- 以下为原脚本业务逻辑,完全保留 ------------------- $mainDir = (Get-Location).Path $subDir = (Get-ChildItem -Path $mainDir | Where-Object { $_.PSIsContainer }).Name foreach ($dir in $subDir) { Write-Host "`n`n **** Directory $dir" if ($runType -eq "download") { $base64token = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes(":$token")) $headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]" $headers.Add("Authorization", "Basic $base64token") $url = "https://dev.azure.com/ASDF/$dir/_apis/git/repositories?api-version=6.1-preview.1" $response = Invoke-RestMethod $url -Method 'GET' -Headers $headers $sortResponse = $response.value | Sort-Object -Property "name" foreach ($item in $sortResponse) { $name = $item.name if (Test-Path -Path "$mainDir\$dir\$name" -PathType "Container") { if (Test-Path -Path "$mainDir\$dir\$name\.git" -PathType "Container") { Set-Location -Path "$mainDir\$dir\$name" Write-Host "`n`t **** Updating Git $name" Write-Host "$mainDir\$dir\$name" # git pull } } else { Set-Location -Path "$mainDir\$dir" Write-Host "`n`t **** Cloning $name" Write-Host "$mainDir\$dir\$name" $clone = "git@ssh.dev.azure.com:v3/ASDF/$dir/$name" # git clone $clone } } } if ($runType -eq "update") { $repos = (Get-ChildItem -Path "$mainDir\$dir" | Where-Object { $_.PSIsContainer }).FullName foreach ($item in $repos) { if (Test-Path -Path "$item\.git" -PathType "Container") { Write-Host "`n`t **** Updating Git $($item.split("\")[-1])" Set-Location -Path $item # git pull } } } } Set-Location -Path $mainDir
关键注意点
- 动态参数的触发时机是PowerShell完成所有静态参数的绑定、校验之后,这时候取到的
runType一定是合法值,不会出现未定义的空值情况 - 动态参数不会像静态参数那样自动在脚本作用域创建同名变量,必须通过
$PSBoundParameters['token']手动取值,否则后续业务逻辑会取不到token的值 - 原脚本里手动判断token缺失的分支完全可以删掉,因为PowerShell的内置校验已经覆盖了这个场景
内容的提问来源于stack exchange,提问作者Beefcake
相关产品推荐
相关产品推荐

