可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'd like to call a PowerShell script this way :
script.ps1 -path mypath\to\files\ -days 6 -hours 0
To validate the command line arguments, I can either do it by hand, either rely on the param
syntax :
Param (
[Parameter(Mandatory=$true )] [string] $path,
[Parameter(Mandatory=$false)] [int] $days,
[Parameter(Mandatory=$false)] [int] $hours
)
If I use the param
syntax :
the param definition must be the first line in the script (excluding comments). Okay, not a problem for me
in case of incorrect parameters, I can't catch the error (for example to display a custom error message)
I'd like to display a custom error message when the script is called with wrong parameters.
Is it possible, and how, to catch the exception in case of parameter error ?
回答1:
So okay, it is not possible to use param
AND to catch the related exceptions.
回答2:
The examples are for functions (simple and advanced) but the same idea should work for scripts with param
as well:
# Simple function.
# Everything not declared in `param` goes to $args.
# If $args is not empty then there are "invalid" parameters or "unexpected" arguments
function test {
param (
[string]$path,
[int]$days,
[int]$hours
)
# check $args and throw an error (in here we just write a warning)
if ($args) { Write-Warning "Unknown arguments: $args" }
}
Or
# Advanced function.
# For an advanced function we can use an extra argument $args
# with an attribute `[Parameter(ValueFromRemainingArguments=$true)]`
function test {
param (
[Parameter(Mandatory=$true )] [string] $path,
[Parameter(Mandatory=$false)] [int] $days,
[Parameter(Mandatory=$false)] [int] $hours,
[Parameter(ValueFromRemainingArguments=$true)] $args
)
# check $args and throw an error (in this test we just write a warning)
if ($args) { Write-Warning "Unknown arguments: $args" }
}
The following test:
# invalid parameter
test -path p -invalid -days 5
# too many arguments
test -path p 5 5 extra
in both cases produces the same output:
WARNING: Unknown arguments: -invalid
WARNING: Unknown arguments: extra
回答3:
A possible workaround is to wrap your actual function in another one. Something similar to a private/public relation. Example:
function Example-Private
{
[CmdletBinding()]
Param
(
[ValidateNotNullOrEmpty()]
[string]$Arg1,
[ValidateNotNullOrEmpty()]
[string]$Arg2
)
# Do what you need
}
function Example-Public
{
[CmdletBinding()]
Param
(
[string]$Arg1,
[string]$Arg2
)
try
{
Example-Private $Arg1 $Arg2
}
catch
{
# Display a user-friendly message, save exception into a log file, etc.
}
}
If you are working on a module you could take a look here how to export your public functions and hide the private ones: Export Powershell Functions
回答4:
In the Begin
block you can always do further validation on the parameters but if the parameter is wrong, I think you wouldn't want to continue execution. That is, you'd want to throw a terminating error. Here's an example:
param (
[Parameter(Mandatory=$true )] [string] $path,
[Parameter(Mandatory=$false)] [int] $days,
[Parameter(Mandatory=$false)] [int] $hours
)
Begin {
if ($hours -lt 0 -or $hours -gt 23) {
throw "Hours parameter must be between 0 and 23"
}
}
That said, I'm not sure that's any better than using PowerShell's built-in parameter validation functionality e.g.:
param (
[Parameter(Mandatory=$true )] [string] $path,
[Parameter(Mandatory=$false)] [int] $days,
[Parameter(Mandatory=$false)]
[ValidateRange(0,23)]
[int]
$hours
)
回答5:
you can do that with the param syntax, if you add a string-type dummy-parameter with the property "ValueFromRemainingArguments".
Then you can check this dummy-parameter in your script and take appropriate actions, e.g.:
Param(
[Parameter(Mandatory=$false)]
[SWITCH]$myparam1,
[Parameter(Mandatory=$false)]
[SWITCH]$myparam2,
[parameter(Mandatory=$false,ValueFromRemainingArguments=$true)]
[STRING]$dummy
)
if ($dummy -eq anythingYouDontLike) throwAMessageOrSomething.