Function 为什么不';我的函数有公共参数吗?
我试图编写一些代码,要求检查函数元数据,并根据命令参数处理一些其他数据。在这个过程中,我发现了一些我无法理解的非常奇怪的行为 我在psm1脚本模块中有一个函数,它是通过导入相邻的psd1模块清单加载的,该清单将它声明为嵌套模块。我已经明确声明了14个参数。当我Function 为什么不';我的函数有公共参数吗?,function,powershell,reflection,parameters,Function,Powershell,Reflection,Parameters,我试图编写一些代码,要求检查函数元数据,并根据命令参数处理一些其他数据。在这个过程中,我发现了一些我无法理解的非常奇怪的行为 我在psm1脚本模块中有一个函数,它是通过导入相邻的psd1模块清单加载的,该清单将它声明为嵌套模块。我已经明确声明了14个参数。当我Get命令并检查参数时,我可以看到它有23个参数。14个是我的;其余的都是 (我的函数名以Install-开头。不过,我的参数不是以数字结尾。这些只是虚拟占位符,因为我不想使用实名。) 这是意料之中的事。函数应该具有公共参数 但为了测试处理
Get命令
并检查参数
时,我可以看到它有23个参数。14个是我的;其余的都是
(我的函数名以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"
}
# 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
然后,当我导入模块时,两个函数都没有任何公共参数:
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
我尝试了一些方法,看看它们是否能带来不同:
- 使用导出模块成员显式导出函数
- 使用将脚本模块作为嵌套模块导入的清单
- 使用脚本并通过
而不是模块将其包括在内\testfunc.ps1
- 直接在shell中定义函数
[CmdletBinding()]
属性修饰其参数(…)
块
然而,正如他自己所发现的,使用每参数[parameter()]
属性隐式地使脚本或函数成为高级脚本或函数
- 但是,请注意,除
-如[parameter()]
或[AllowNull()]
之外的每参数属性本身并不构成脚本/函数和高级函数[Alias()]
发现给定脚本/函数是否高级(支持公共参数)的一种简便方法是将其名称传递给
获取帮助
:
$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"
}
# 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 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
# 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