当前位置: 首页 > 知识库问答 >
问题:

catch块中的Powershell异常导致意外的执行流

宋臻
2023-03-14

我试图理解为什么下面的代码打印“我不应该被打印!!"

try块中的代码抛出一个错误,当它的errorAction变量被设置为stop时,Ppowershell将执行相应的catch块。

在catch中,测试函数调用将失败(因为测试函数参数属性validateSet不包括“facdfsd”)并抛出明显不终止的异常:ParameterArgumentValidationError

我现在期望执行在测试函数调用后继续在该行,打印“捕获异常”并退出,但它跳出捕获块并继续执行打印“我不应该打印!!”。

我错过了什么?

谢谢,大卫

function test-function{
[CmdletBinding()]
PARAM(
    [Parameter(Mandatory)]
    [ValidateSet('OnlyAcceptThisStringAndNothingElse')]
    [ValidateNotNullOrEmpty()]
    [string]$param
)
    write-output "Executed"

}

try{
    ## throws an error to enter the catch block
    get-childitem nonexisting -ea stop
}
catch{
    ## test-function does not accept this param and throws an error
    test-function -param "fasdfsd"
    ## this should be executed anyway but it isn't
    write-output "caught exception"
    ## the script should quit here
    exit
}
## this Should not have been executed but it is
write-output "I shouldn't be printed!!"

共有1个答案

狄誉
2023-03-14

@beatcracker如果在非终止异常之后一切正常,则执行应继续执行下一条指令,即写入输出“捕获异常”,并在命令“退出”后不久退出脚本。

-大卫·塔莱斯科

我同意,我不清楚这一点。我的意思是,它总是以这种方式工作 - 必须将捕获块内的所有内容包装到另一个尝试/捕获中,否则它只会在非终止错误时默默地退出捕获脚本块并继续执行接下来出现的任何代码。

internal void InvokeWithPipe(bool useLocalScope, bool writeErrors, object dollarUnder, object input, object scriptThis, Pipe outputPipe, ref ArrayList resultList, params object[] args)
{
    ExecutionContext contextFromTLS = this.GetContextFromTLS();
    if (contextFromTLS.CurrentPipelineStopping)
    {
        throw new PipelineStoppedException();
    }
    ParseTreeNode codeToInvoke = this.GetCodeToInvoke();
    if (codeToInvoke != null)
    {
        InvocationInfo invocationInfo = new InvocationInfo(null, codeToInvoke.NodeToken, contextFromTLS);
        contextFromTLS.Debugger.PushMethodCall(invocationInfo, this);
        bool flag = false;
        ScriptInvocationContext oldScriptContext = null;
        Pipe shellFunctionErrorOutputPipe = null;
        CommandOrigin scopeOrigin = contextFromTLS.EngineSessionState.currentScope.ScopeOrigin;
        Exception exception = null;
        SessionStateInternal engineSessionState = contextFromTLS.EngineSessionState;
        ActivationRecord oldActivationRecord = null;
        try
        {
            ScriptInvocationContext scriptContext = new ScriptInvocationContext(useLocalScope, scriptThis, dollarUnder, input, args);
            this.EnterScope(contextFromTLS, scriptContext, out oldScriptContext, out oldActivationRecord);
            shellFunctionErrorOutputPipe = contextFromTLS.ShellFunctionErrorOutputPipe;
            if (!writeErrors)
            {
                contextFromTLS.ShellFunctionErrorOutputPipe = null;
            }
            contextFromTLS.EngineSessionState.currentScope.ScopeOrigin = CommandOrigin.Internal;
            if (!string.IsNullOrEmpty(this.File))
            {
                contextFromTLS.Debugger.PushRunning(this.File, this, false);
                flag = true;
            }
            codeToInvoke.Execute(null, outputPipe, ref resultList, contextFromTLS);
        }
        catch (ReturnException exception2)
        {
            if (!this._isScriptBlockForExceptionHandler)
            {
                ParseTreeNode.AppendResult(contextFromTLS, exception2.Argument, null, ref resultList);
            }
            else
            {
                exception = exception2;
            }
        }
        finally
        {
            if (flag)
            {
                contextFromTLS.Debugger.PopRunning();
            }
            contextFromTLS.ShellFunctionErrorOutputPipe = shellFunctionErrorOutputPipe;
            contextFromTLS.EngineSessionState.currentScope.ScopeOrigin = scopeOrigin;
            try
            {
                this.LeaveScope(contextFromTLS, oldScriptContext, engineSessionState, oldActivationRecord);
            }
            finally
            {
                contextFromTLS.Debugger.PopMethodCall();
            }
        }
        if (exception != null)
        {
            throw exception;
        }
    }
}

catch的脚本块由内部密封类< code > exception handler node 的方法< code>Invoke在< code > _ isScriptBlockForExceptionHandler 设置为< code>true的情况下创建,该方法从前面提到的公共类< code>ScriptBlock中调用< code > CreateExceptionHandler :

internal static ScriptBlock CreateExceptionHandler(ParseTreeNode body, Token token, int pipelineSlots, int variableSlots)
{
    return new ScriptBlock(token, null, null, null, null, body, null, false, null, null, null, pipelineSlots, variableSlots) { _isScriptBlockForExceptionHandler = true };
}

请注意,当<code>_ISScript BlockForExceptionHandler

catch (ReturnException exception2)
{
    if (!this._isScriptBlockForExceptionHandler)
    {
        ParseTreeNode.AppendResult(contextFromTLS, exception2.Argument, null, ref resultList);
    }
    else
    {
        exception = exception2;
    }
}

我不清楚AppendResult方法做了什么,但我发现:

调用AppendResult方法主要是从返回的对象调用公共属性的getters,以检索将被写入输出控制台的值。

 类似资料:
  • 本文向大家介绍说明PowerShell中的Try / Catch / Finally块,包括了说明PowerShell中的Try / Catch / Finally块的使用技巧和注意事项,需要的朋友参考一下 PowerShell中的Try / Catch块用于处理脚本中产生的错误。具体而言,错误应该是终止错误。在最后在PowerShell中块不是强制性的,每次沿写try / catch语句,但它会

  • EDIT应该返回true或false,但它的抛出错误

  • 问题内容: 我正在尝试收集所有发生的异常计数和a中的异常名称,以便我应该知道该异常发生了多少次。 因此,在我的catch块中,我有一个映射,该映射将继续添加异常名称,并且总计数出现。 下面是我每次用于测试目的的代码,以便我可以看到异常计数是否正确。 所以某些情况下 1)如果我将线程数选择为,将任务数选择为,则在该图中,我可以看到该特定字符串的500个异常 2)但是,如果我选择的线程数和任务数一样,

  • 我有一个文件,我需要读取,打印出整数,捕获异常并继续显示下一个整数,依此类推,直到没有更多的整数。 该文件包含:12 5 sd 67 4 cy 我想让它显示: 12 5 输入错误67 4 输入错误 但是,它只给我12,5,接着输入错误,它就停了。我尝试过将所有内容放入while循环中,但它会无休止地循环,并出现输入异常。 我错过了什么,以便循环继续读取下一个int等等?

  • 问题内容: 可以在Swift中捕获异常吗?给出以下代码: 是否可以防止异常导致整个程序崩溃?也就是说,Objective-C中的Swift等效于什么: 问题答案: 它没有异常处理,并且在开发人员论坛中的讨论讨论了为什么会这样: 但请记住,可可和可可触控传统上并不打算让您捕获异常。他们打算让您不要将它们放在首位。普通错误应使用可选类型和inout NSError参数处理;您应该通过编写更好的代码来解

  • 这是我的脚本,它返回一个布尔值 我希望脚本打印捕获的异常,并返回布尔值,但在本例中,脚本失败时只返回false。感谢您的帮助,我需要打印异常,就像try-catch块不存在一样。