所以我想做的是重新创建一个与Bash中使用的功能类似的功能,但要在Powershell中使用
:yell() { echo "$0: $*" >&2; }
die() { yell "$*"; exit 111; }
try() { "$@" || die "FAILED: $*"; }
此刻我最感兴趣的部分是try()函数。从本质上讲,它的作用是让我使用此功能包装命令并让其管理退出代码。效果是这样的:
try doSomething -args
如果doSomething
以非零值退出,它将向stderr输出命令并停止脚本执行。
我意识到Powershell有一个错误操作,可用于中止脚本,但似乎只适用于Commandlet。我需要可以在整个脚本中使用的任何东西。我还希望避免大量冗长的try / catch逻辑使脚本混乱,因此希望获得诸如try / yell / die之类的优雅内容。这样,我可以单独在此函数中编写处理,然后使用它来调用要处理的任何内容。
我找到了$MyInvocation
并认为这可能是解决方法,但是我似乎找不到从函数内部实际执行它的方法。例如:
function run() {
$MyInvocation # ?? what do??
}
run doSomething -args
我想我可以自己解决其余的问题,我只是不太了解如何编写此包装函数。有什么想法吗?
因此,我做了一些俗气的事情,我对该命令进行了细化处理,并对剩下的内容进行了Invoke-Expression
的修改,看来它可以正常工作。感觉超级hacky,所以我仍然愿意接受想法:
function attempt() {
$thisCommand = $MyInvocation.Line.Trim()
Write-Output $thisCommand
Invoke-Expression $thisCommand.Substring(8)
if($LASTEXITCODE -ne 0) {
throw "Command failed $thisCommand"
exit 111
}
}
attempt doSomething -args
答案 0 :(得分:1)
如果您希望函数运行任意命令并在该命令失败时引发错误,则可以执行以下操作:
function Test-Command {
try {
$cmd, $params = $args
$params = @($params)
$global:LastExitCode = 0
$output = & $cmd @params 2>&1
if ($global:LastExitCode -ne 0) {
throw $output
}
$output
} catch {
throw $_
}
}
故障:
$cmd, $params = $args
接受automatic variable $args
(传递给函数的参数数组),并将其第一个元素分配给变量$cmd
,其余元素分配给变量$params
。
$params = @($params)
确保$params
包含一个数组(下一步需要),即使该变量为空或仅具有单个值也是如此。
& $cmd @params
使用call operator &
调用命令,而splatting使用参数。 Do NOT use Invoke-Expression
。
redirection operator 2>&1
将错误输出与常规输出合并,以便将两个输出流都捕获到变量$output
中。
如果$cmd
是 PowerShell cmdlet ,则错误将引发异常,该异常将由try
语句捕获。 try
块中的其余代码将被跳过。但是请注意,并非所有PowerShell cmdlet引发的错误都会自动终止错误(例如,参见Scripting Guy博客上的"An Introduction to Error Handling in PowerShell")。要将非终止错误转换为终止错误,您需要设置$ErrorActionPreference = 'Stop'
(完成后将其重置为原始值)。
如果$cmd
是外部命令,则错误不会引发异常,但是自动变量$LastExitCode
会使用命令的退出代码进行更新。返回非零退出代码的命令将触发if
条件,并使用命令输出作为异常消息来引发自定义异常。然后,该异常也会被try
语句捕获。 try
块中的其余代码再次被跳过。
$global:LastExitCode = 0
在每次运行之前重置变量$LastExitCode
。这是必需的,因为只有外部命令会返回退出代码,而PowerShell cmdlet不会。由于$LastExitCode
保留了当前会话中上次运行的外部命令的退出代码,因此不重置变量将使在执行外部命令后运行的PowerShell cmdlet的状态检测变得混乱。
仅在命令既不引发异常也不返回非零退出代码的情况下,才到达try
块的最后一行,该行回显捕获的命令输出。
任何捕获到的异常都在catch
块中进行处理,该块只是将异常传递给函数的调用者。当然,除了抛出错误外,您还可以输出错误并退出。