function - 为什么我的函数没有公共(public)参数?

标签 function powershell reflection parameters

我正在尝试编写一些代码,这些代码需要检查函数元数据并根据命令的参数处理一些其他数据。在此过程中,我发现了一些我无法理解的非常奇怪的行为。

我在 psm1 脚本模块中有一个函数,它是通过导入将其声明为嵌套模块的相邻 psd1 模块 list 来加载的。我已经明确声明了 14 个参数。当我 Get-Command 并检查 Parameters 时,我可以看到它有 23 个参数。 14个是我的;其余的是 common parameters .

PS> (Get-Command Install-MyFunctionFromModule).Parameters.Count
23
PS> (Get-Command Install-MyFunctionFromModule).Parameters.keys
MyParameter1
MyParameter2
MyParameter3
MyParameter4
MyParameter5
MyParameter6
MyParameter7
MyParameter8
MyParameter9
MyParameter10
MyParameter11
MyParameter12
MyParameter13
MyParameter14
Verbose
Debug
ErrorAction
WarningAction
ErrorVariable
WarningVariable
OutVariable
OutBuffer
PipelineVariable

(我的函数名称​​确实Install-开头。不过,我的参数不以数字结尾。这些只是虚拟占位符,因为我不想使用真实姓名。)

这是意料之中的事情。函数应该有共同的参数。

但是为了测试处理参数的代码,我尝试创建一个测试模块。这是它的样子:

testfun.psm1:

$ErrorActionPreference = 'Stop'
Set-StrictMode -Version Latest

function test-noparams() {
    Write-Host 'None'
}

function test-differentnamedparams([string]$hello, [switch]$bye) {
    Write-Host "names that don't conflict with common params"
}

然后当我导入模块时,两个函数都没有任何公共(public)参数:

PS> Import-Module .\testfunc.psm1
PS> (Get-Command test-differentnamedparams).Parameters.Count
2
PS> (Get-Command test-differentnamedparams).Parameters | Format-Table -AutoSize

Key   Value
---   -----
hello System.Management.Automation.ParameterMetadata
bye   System.Management.Automation.ParameterMetadata

PS> (Get-Command test-noparams).Parameters.Count
0

我已经尝试了一些方法,看看它们是否有所不同:

  • 使用 Export-ModuleMember 显式导出函数
  • 使用将脚本模块导入为 NestedModule
  • 的 list
  • 使用脚本并通过 包含它。 .\testfunc.ps1 而不是模块
  • 直接在 shell 中定义函数

他们都没有改变任何东西。

什么决定了一个函数是否有公共(public)参数?什么会导致他们不这样做?

最佳答案

advanced functions or scripts支持common parameters .

使脚本/函数成为高级函数的显式方法是用 param(...) block 装饰 < strong>[CmdletBinding()] 属性。

然而,作为jpmc26他自己发现,使用每个参数 [Parameter()] 属性隐式地使脚本或函数更高级

  • 但是,请注意每个参数的属性 other [Parameter()] - 例如 [AllowNull()][Alias()] - 自己制作脚本/函数和高级函数。

一种发现给定脚本/函数是否高级(支持通用参数)的简单方法是将其名称传递给Get-Help:

# Define a NON-advanced function - no [CmdletBinding()] or [Parameter()] attributes.
PS> function foo { param([string] $bar) 'hi' }; Get-Help foo

NAME
    foo

SYNTAX
    foo [[-bar] <string>]  


ALIASES
    None


REMARKS
    None
# Define an ADVANCED function EXPLICITLY - note the [CmdletBinding()] attribute
# BEFORE the param(...) block.
PS> function foo { [CmdletBinding()] param([string] $bar) 'hi' }; Get-Help foo

NAME
    foo

SYNTAX
    foo [[-bar] <string>]  [<CommonParameters>]


ALIASES
    None


REMARKS
    None
# Define an ADVANCED function IMPLICITLY - note the [Parameter(Mandatory)] attribute 
# FOR PARAMETER $bar.
PS> function foo { param([Parameter(Mandatory)] [string] $bar) 'hi' }; Get-Help foo

NAME
    foo

SYNTAX
    foo [[-bar] <string>]  [<CommonParameters>]


ALIASES
    None


REMARKS
    None

可选阅读:陷阱:名称与通用参数的冲突

从 PSv5.1 开始:

jpmc26还发现,如果您不小心声明了一个名称与通用参数名称冲突的参数,您在定义函数时不会收到错误,但只会在稍后调用它,包括将其传递给 Get-Help:

# Define advanced function that mistakenly names a a parameter for
# a common parameter:
PS> function foo { [CmdletBinding()] param([string] $Verbose) 'hi' }
# NO error is reported at this point.

# Later invocation of the function, including introspection of its parameters
# when you pass it to Get-Help, then surfaces the problem:
PS> Get-Help foo
Get-Help : A parameter with the name 'Verbose' was defined multiple times for the command.
At line:1 char:1
+ Get-Help foo
+ ~~~~~~~~~~~~
    + CategoryInfo          : MetadataError: (:) [Get-Help], MetadataException
    + FullyQualifiedErrorId : ParameterNameAlreadyExistsForCommand,Microsoft.PowerShell.Commands.GetHelpCommand

关于function - 为什么我的函数没有公共(public)参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42591569/

相关文章:

c++ - 更改表条目没有重定向功能?

windows - 如果脚本具有强制参数,则 Powershell 调用函数

powershell - 调试Powershell登录网页脚本

C# 派生泛型类型参数

php - PHP/Python/Etc 中内置函数的 ctags 信息

python - 为数据框创建 Parquet 创建函数

variables - powershell 将 ps1 脚本的输出分配给变量

c# - 在沙箱 AppDomain 中执行反射方法时出现 SecurityException

c# - .NET反射如何确定方法返回类型(包括void)和参数?

r - 使用 purrr 按向量中的值进行过滤