PowerShell ThrowterminationError()错误不是真的终止错误
这要么是bug报告的前奏,要么是关于设计逻辑和实用性的问题。 在任何情况下,一个关于如何开发具有真正终止错误的cmdlet的问题 在干净会话中,即使用PowerShell ThrowterminationError()错误不是真的终止错误,powershell,Powershell,这要么是bug报告的前奏,要么是关于设计逻辑和实用性的问题。 在任何情况下,一个关于如何开发具有真正终止错误的cmdlet的问题 在干净会话中,即使用$ErrorActionPreference='Continue'而不使用 尝试或陷阱,调用以下任何命令(甚至一起调用): 因此,“继续!”。 结果表明,该方法终止命令本身,但不终止调用脚本 这些只是一些人为的例子,还有很多其他的例子。 例子并不真实,但这个问题有时是真实的 请注意,-ErrorAction Stop没有帮助,它不是为此类错误而设计
$ErrorActionPreference='Continue'
而不使用
尝试
或陷阱
,调用以下任何命令(甚至一起调用):
因此,“继续!”在每个使用throwterminationgeror()的命令之后调用code>
。
结果表明,该方法终止命令本身,但不终止调用脚本
这些只是一些人为的例子,还有很多其他的例子。
例子并不真实,但这个问题有时是真实的
请注意,-ErrorAction Stop
没有帮助,它不是为此类错误而设计的。
它影响非终止错误(WriteError()
,写入错误
)
还有一个实际问题:有没有一种方法可以发出终止错误
正在终止当前命令和调用脚本
在脚本中,这看起来可以(在某些情况下,不是全部):
请注意,抛出“message”
实际上是终止。
但是写入错误和throwterminingerror()
有重要区别。
它的错误位置指向throw
行。这并不总是像以前那样有用
命令调用失败的行,特别是在语法或
输入问题,即按性质终止问题
所以脚本有一些东西。但是cmdlet可以做什么呢?
可用的WriteError()
未终止。
原始throw
与throwterminingerror()
没有太大区别
更新
实际上,$ErrorActionPreference='Stop'
使通过TerminationError()
在调用脚本中终止。所以请尝试和陷阱
这不是我要找的。我特别指出了$ErrorActionPreference
='Continue'
,默认设置。我在寻找绝对终止错误
不管是否使用默认设置。相比之下,在脚本中,抛出总是
终止(尽管它不是完美的,如前所述)。我在找那个
.NET cmdlet中的模拟
用户忘记设置$ErrorActionPreference='Stop'
。我有时会忘记这一点。
有些情况下,比如无效命令,应该停止调用脚本
设置。至少命令作者应该能够选择此选项
“结果,”接着说在使用throwterminingerror()的每个命令之后调用。结果表明,该方法终止命令本身,但不终止调用脚本
当然不是-您的$ErrorActionPreference
设置为Continue
-因此当cmdlet调用引发错误时,repl(或脚本)只需继续(Continues)执行
$ErrorActionPreference
是其定义范围的本地项,因此您可以在函数或脚本中设置它以覆盖用户的首选项(但仅在函数/脚本的范围内):
script.ps1
它将在Save Module
出错后立即返回(即使调用范围中$ErrorActionPreference
设置为Continue
)您可以在PowerShell throw中抛出与throw
语句相同的异常:
Add-Type -TypeDefinition @‘
using System;
using System.Management.Automation;
[Cmdlet(VerbsDiagnostic.Test, "Throw")]
public class TestThrow : Cmdlet {
protected override void ProcessRecord() {
throw new RuntimeException("Message") { WasThrownFromThrowStatement=true };
}
}
’@ -PassThru|Select-Object -First 1 -ExpandProperty Assembly|Import-Module
Test-Throw; 'Not printed'
在脚本中,可以这样做(需要调用内部方法):
对于C#cmdlet,似乎同样需要:
否则,它会将整个语句下划线为错误,而不仅仅是一个命令:
Test-Throw | % { Some other command }; 'Not printed'
这不是我要找的。我特别提到了$ErrorActionPreference='Continue'
。无论默认设置是否正确,我都在查找绝对终止错误。例如,在脚本中,抛出总是终止。我正在寻找.NET cmdlet中的类似版本。用户忘记设置$ErrorActionPreference='Stop'
。我有时会忘记这一点。在某些情况下,例如无效命令,不管设置如何,都应该停止调用脚本。至少authours应该能够选择此选项。@RomanKuzmin您可以在任何子作用域内设置它,而不影响调用作用域,请参见“应答器更新”。我个人认为当前行为是一个bug或设计缺陷。在将此作为bug或建议提交之前,我想问一下这种设计的合理性或有用性。@RomanKuzmin原因很简单-安全性。通过允许一段代码的作者退出调用者范围,您颠覆了用户控件,坏的ideaIt看起来是一个可能的答案。让我在各种场景中尝试一下。遗憾的是,$PSCmdlet.ThrowTerminatingError()
仍然没有使用这种适用于.NET cmdlet的技巧来终止。找到解决办法也很好。有什么神奇的想法吗?@RomanKuzmin脚本是可能的,但它需要使用内部方法。如果不是太糟糕的话,知道它会很有趣。至少为了更好的理解。
[CmdletBinding()]
param()
$ErrorActionPreference = 'Stop'
# script module, missing path
Save-Module InvokeBuild -Path zzz -ErrorAction Stop; 'Continued!'
# cmdlet, invalid data
ConvertFrom-Json zzz -ErrorAction Stop; 'Continued!'
# cmdlet, invalid command syntax
Get-Module -Name zzz -FullyQualifiedName zzz -ErrorAction Stop; 'Continued!'
Export-Csv -Path zzz -LiteralPath zzz -InputObject 1 -ErrorAction Stop; 'Continued!'
Add-Type -TypeDefinition @‘
using System;
using System.Management.Automation;
[Cmdlet(VerbsDiagnostic.Test, "Throw")]
public class TestThrow : Cmdlet {
protected override void ProcessRecord() {
throw new RuntimeException("Message") { WasThrownFromThrowStatement=true };
}
}
’@ -PassThru|Select-Object -First 1 -ExpandProperty Assembly|Import-Module
Test-Throw; 'Not printed'
function Test-ScriptThrow {
$ErrorRecordType = [System.Management.Automation.ErrorRecord]
$ErrorRecord = $ErrorRecordType::new([Exception]::new("Message"), 'ErrorId', 'NotSpecified', $null)
$ErrorRecordType.InvokeMember('SetInvocationInfo', 'Instance, NonPublic, InvokeMethod', $null, $ErrorRecord, $MyInvocation)
throw $ErrorRecord
}
Test-ScriptThrow; 'Not printed'
Add-Type -TypeDefinition @‘
using System;
using System.Reflection;
using System.Management.Automation;
[Cmdlet(VerbsDiagnostic.Test, "Throw2")]
public class TestThrow2 : PSCmdlet {
protected override void ProcessRecord() {
ErrorRecord errorRecord = new ErrorRecord(new Exception("Message"), "ErrorId", ErrorCategory.NotSpecified, null);
typeof(ErrorRecord).InvokeMember("SetInvocationInfo", BindingFlags.Instance|BindingFlags.NonPublic|BindingFlags.InvokeMethod, null, errorRecord, new[] { MyInvocation });
throw new RuntimeException(null, null, errorRecord) { WasThrownFromThrowStatement=true };
}
}
’@ -PassThru|Select-Object -First 1 -ExpandProperty Assembly|Import-Module
Test-Throw2 | % { Some other command }; 'Not printed'
Test-Throw | % { Some other command }; 'Not printed'