Powershell 如何以正确的参数类型返回参数的默认值?

Powershell 如何以正确的参数类型返回参数的默认值?,powershell,Powershell,下面的代码将检索函数或脚本文件中使用的参数的默认值: Function Get-DefaultParameterValuesHC { [OutputType([hashtable])] Param ( [Parameter(Mandatory)] [String]$Path ) $ast = (Get-Command $Path).ScriptBlock.Ast $selectParams = @{ Pro

下面的代码将检索函数或脚本文件中使用的参数的默认值:

Function Get-DefaultParameterValuesHC {
    [OutputType([hashtable])]
    Param (
        [Parameter(Mandatory)]
        [String]$Path
    )
    $ast = (Get-Command $Path).ScriptBlock.Ast

    $selectParams = @{
        Property = @{ 
            Name       = 'Name'; 
            Expression = { $_.Name.VariablePath.UserPath } 
        },
        @{ 
            Name       = 'Value'; 
            Expression = { 
                if ($_.DefaultValue.StaticType.IsArray) {
                    $_.DefaultValue.SubExpression.Statements.PipelineElements.Expression.Elements.Extent.Text
                }
                else {
                    if ($_.DefaultValue.Value) { $_.DefaultValue.Value }
                    else { $_.DefaultValue.Extent.Text }
                }
            }
        }
    }
    
    $result = @{ }

    $defaultValueParameters = @($ast.FindAll( {
        $args[0] -is [System.Management.Automation.Language.ParameterAst] } , 
        $true) | Where-Object { $_.DefaultValue } | 
        Select-Object @selectParams)
        
    foreach ($d in $defaultValueParameters) {
        $result[$d.Name] = foreach ($value in $d.Value) {
            # Convert '$env:' variables
            $ExecutionContext.InvokeCommand.ExpandString($value) -replace 
            "^`"|`"$|'$|^'" 
        }
    }
    $result
}

但是,所有值的类型均为
string
。如何才能使它们具有正确的类型?下面的示例说明了哈希表作为字符串返回的问题

Function Test-Function {
    Param (
        [String]$ScriptName = 'Get printers',
        [HashTable]$Settings = @{ Duplex = 'Yes'}
    )
}
Get-DefaultParameterValuesHC -Path 'Test-Function'

# Output:
Name         Value
----         -----
ScriptName   'Get printers'
PaperSize    '@{ Duplex = 'Yes'}'  # String not hashTable

但只有当它不是一种表达时,它才起作用。有没有办法让它也适用于哈希表?

首先,可以通过以下方式直接提取参数:

$ast.Body.ParamBlock.Parameters
在这种情况下不需要
FindAll()

实现这一点的一种快速而肮脏的方法是让
Select Object
参数splat返回文本表示,而不管数据类型如何,并在处理结果时使用该方法对其进行解析:

Name = 'Value';
Expression = {
    $_.DefaultValue.Extent.Text
}
请注意,
InvokeScript()
将执行传递给它的任何字符串。因此,与
调用表达式
一样,无论何时使用,都要小心。例如,如果
Test Function
在其
param()
块中有此项:

[String]$ScriptName = (& cmd /c "echo This ran >%USERPROFILE%\Desktop\OhNo.txt"),
如上所述运行分析函数将运行
cmd
并编写一个文件,即使它没有显式调用目标函数。因此,将此方法用于运行
param()
块中命令的函数是有风险的。有必要递归地查看每个
DefaultValue
Pipeline
SubExpression
属性,以过滤掉不应该解析的任何内容


可以根据每个
DefaultValue
的属性识别大多数类型,并自定义每个数据类型的行为以重新创建原始对象。与问题中的代码已经将数组与其他类型区分开来的方式类似,精致的类型处理是迄今为止最安全的方法。

感谢您提供的帮助和见解。需要注意的是,
$ast.Body.ParamBlock.Parameters
仅适用于函数,而
$ast.ParamBlock.Parameters
仅适用于脚本文件。因此,我们仍然必须坚持使用
FindAll()
以获得一致的方法`不客气
Get命令
返回扩展脚本、函数等的不同类型的CommandInfo。它们都有一个属性
CommandType
,可用于决定选择哪个分支。我用switch语句试过了。
[String]$ScriptName = (& cmd /c "echo This ran >%USERPROFILE%\Desktop\OhNo.txt"),