Trying to get get param(...) to be have some basic error checking... one thing that puzzles me is how to detect invalid switch and flags that are not in the param list?
function abc {
param(
[switch]$one,
[switch]$two
)
}
When I use it:
PS> abc -One -Two
# ok... i like this
PS> abc -One -Two -NotAValidSwitch
# No Error here for -NotAValidSwitch? How to make it have an error for invalid switches?
CodePudding user response:
As Santiago Squarzon, Abraham Zinala, and zett42 point out in comments, all you need to do is make your function (or script) an advanced one:
explicitly, by decorating the
param(...)
block with a[CmdletBinding()]
attribute.and/or implicitly, by decorating at least one parameter variable with a
[Parameter()]
attribute.
function abc {
[CmdletBinding()] # Make function an advanced one.
param(
[switch]$one,
[switch]$two
)
}
An advanced function automatically ensures that only arguments that bind to explicitly declared parameters may be passed.
If unexpected arguments are passed, the invocation fails with a statement-terminating error.
Switching to an advanced script / function has side effects, but mostly beneficial ones:
You gain automatic support for common parameters, such as
-OutVariable
or-Verbose
.You lose the ability to receive unbound arguments, via the automatic
$args
variable variable (which is desired here); however, you can declare a catch-all parameter for any remaining positional arguments via[Parameter(ValueFromRemainingArguments)]
To accept pipeline input in an advanced function or script, a parameter must explicitly be declared as pipeline-binding, via
[Parameter(ValueFromPipeline)]
(objects as a whole) or[Parameter(ValueFromPipelineByPropertyName)]
(value of the property of input objects that matches the parameter name) attributes.
For a juxtaposition of simple (non-advanced) and advanced functions, as well as cmdlets, see this answer.
If you do not want to make your function an advanced one:
Check if the automatic $args
variable - reflecting any unbound arguments (a simpler alternative to $MyInvocation.UnboundArguments
) - is empty (an empty array) and, if not, throw an error:
function abc {
param(
[switch]$one,
[switch]$two
)
if ($args.Count) { throw "Unexpected arguments passed: $args" }
}
CodePudding user response:
PS> function x { write-host $MyInvocation.UnboundArguments.Count }
PS> x -sdfsdf
1
PS> x -sdfsdf -sdfsd
2
PS> x
0
if ($MyInvocation.UnboundArguments.Count -ne 0) {
throw "invalid argument"
}
CodePudding user response:
If you want to avoid M$'s strange CmdLet System... then, this works: Save this to a file.ps1 script:
<#
.SYNOPSIS
This is the Script synopsys
.DESCRIPTION
This is the Script description
.PARAMETER New
about switch new
.PARAMETER File
about flag file
.EXAMPLE
PS> sign -File *.ps1
#>
param(
[switch]$New,
[string[]]$File
)
try {
$ErrorActionPreference = 'Stop'
# Don't allow any arguments that are not bound to param(..)
if ($MyInvocation.UnboundArguments.Count -ne 0) {
throw "invalid argument"}
# Show Help if there are no arguments
if ($PSBoundParameters.Count -eq 0) {
Get-Help -Detailed $MyInvocation.MyCommand.Path; exit 1}
}
catch {
write-host "EXCEPTION: $_"
}
its ashamed to mess up a good scripting language in order to add weird cmdlets pipelining stuff that most people don't need for ordinary scripting tasks...
Just always accept arguments with param... and never use unbound...