我希望我的PowerShell脚本在我运行的任何命令失败时停止(如bash中的set -e)。我正在使用Powershell命令(New-Object System.Net.WebClient)和程序(.\setup.exe)。
当前回答
重定向stderr到stdout似乎也没有任何其他命令/scriptblock包装的技巧,尽管我找不到一个解释为什么它是这样工作的。
# test.ps1
$ErrorActionPreference = "Stop"
aws s3 ls s3://xxx
echo "==> pass"
aws s3 ls s3://xxx 2>&1
echo "shouldn't be here"
这将如预期的那样输出以下内容(命令aws s3…返回$LASTEXITCODE = 255)
PS> .\test.ps1
An error occurred (AccessDenied) when calling the ListObjectsV2 operation: Access Denied
==> pass
其他回答
看来简单的重掷就行了。
param ([string] $Path, [string] $Find, [string] $Replace)
try {
((Get-Content -path $Path -Raw) -replace $Find, $Replace) | Set-Content -Path $Path
Write-Output Completed.
} catch {
# Without try/catch block errors don't interrupt program flow.
throw
}
现在只有在成功执行之后才会出现输出Completed。
据我所知,Powershell对它调用的子程序返回的非零退出码没有任何自动处理。
到目前为止,我所知道的模仿bash -e行为的唯一解决方案是在每次调用外部命令后添加这个检查:
if(!$?) { Exit $LASTEXITCODE }
对@alastairtree的回答做了一点修改:
function Invoke-Call {
param (
[scriptblock]$ScriptBlock,
[string]$ErrorAction = $ErrorActionPreference
)
& @ScriptBlock
if (($lastexitcode -ne 0) -and $ErrorAction -eq "Stop") {
exit $lastexitcode
}
}
Invoke-Call -ScriptBlock { dotnet build . } -ErrorAction Stop
这里的关键区别是:
它使用动词-名词(模仿Invoke-Command) 暗示它在幕后使用调用操作符 模仿内置cmdlet中的-ErrorAction行为 使用相同的退出代码退出,而不是使用新消息抛出异常
您应该能够通过在脚本的开头使用语句$ErrorActionPreference = "Stop"来实现这一点。
$ErrorActionPreference的默认设置是Continue,这就是为什么你看到你的脚本在错误发生后继续运行。
不幸的是,由于有bug的cmdlet,如New-RegKey和Clear-Disk,这些答案都不够。我目前在一个名为ps_support.ps1的文件中确定了以下代码:
Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
$PSDefaultParameterValues['*:ErrorAction']='Stop'
function ThrowOnNativeFailure {
if (-not $?)
{
throw 'Native Failure'
}
}
然后在任何powershell文件中,在文件(如果存在)的CmdletBinding和Param之后,我有以下内容:
$ErrorActionPreference = "Stop"
. "$PSScriptRoot\ps_support.ps1"
重复的ErrorActionPreference = "Stop"行是有意的。如果我犯了错误,以某种方式获得了ps_support的路径。Ps1错了,那需要的不是默默的失败!
我保留ps_support。Ps1位于我的repo/workspace的公共位置,因此点源的路径可能会根据当前. Ps1文件的位置而改变。
任何本地调用都会得到这样的处理:
native_call.exe
ThrowOnNativeFailure
在编写powershell脚本时,使用该文件进行点源可以帮助我保持头脑清醒。: -)
推荐文章
- 如何运行一个PowerShell脚本而不显示窗口?
- PowerShell:仅为单个命令设置环境变量
- 是否有一种方法可以通过双击.ps1文件来使PowerShell脚本工作?
- 为什么这个Windows批处理文件只执行第一行,而在命令shell中执行所有三行?
- 环境变量存储在Windows注册表的哪里?
- 有一个好的Valgrind Windows的替代品吗?
- Windows和Linux上的c++编译:ifdef开关
- 如何验证批处理文件中是否存在一个文件?
- PowerShell等价于grep -f
- “Write-Host”,“Write-Output”,或“[console]::WriteLine”之间的区别是什么?
- XAMPP -端口80被PID 4的“无法打开进程”使用!12
- 为什么git在Windows下记不住我的密码
- Powershell相当于bash的&号(&),用于分叉/运行后台进程
- Git克隆/拉不断冻结在“存储密钥在缓存?”
- PowerShell脚本在机器上返回。net框架的版本?