Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/powershell/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
捕获块中的Powershell异常导致意外的执行流_Powershell_Error Handling_Try Catch_Throw - Fatal编程技术网

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

捕获块中的Powershell异常导致意外的执行流,powershell,error-handling,try-catch,throw,Powershell,Error Handling,Try Catch,Throw,我试图理解为什么下面的代码会打印“我不应该被打印!!” try块中的代码抛出错误,当其errorAction变量设置为stop时,Ppowershell将执行相应的catch块 在catch测试中,函数调用将失败(因为测试函数param属性validateSet不包括“fasdfsd”),并抛出明显未终止的异常:ParameterArgumentValidationError 我现在希望在测试函数调用后,执行会在第行继续,打印“捕获的异常”并退出,但它会跳出catch块并继续执行打印“我不应该被

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

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

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

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

我错过了什么

谢谢, 戴维德

@beatcracker如果在非 终止异常执行应继续执行下一个异常 写入输出为“捕获异常”的指令,并且不久之后 应该退出脚本的命令“exit”

-戴维德·塔莱斯科

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


下面不是一个真正的答案,只是一个想法,希望更熟练的人能从中有所收获。
虽然我不能很好地理解它为什么这样做,但我想我在
System.Management.Automation
assembly(
public class ScriptBlock
)中将它本地化为这段代码:

catch的ScriptBlockforExceptionHandler设置为
true
时,由内部密封类
ExceptionHandlerNode
的方法
Invoke
创建脚本块,该方法从上述公共类
ScriptBlock
调用
CreateExceptionHandler

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;
        }
    }
}
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 };
}
请注意,当
\u isScriptBlockForExceptionHandler
设置为
true
时,当在上面的
InvokeWithPipe
方法中执行catch块时,如果发生异常,则不会引发异常:

catch (ReturnException exception2)
{
    if (!this._isScriptBlockForExceptionHandler)
    {
        ParseTreeNode.AppendResult(contextFromTLS, exception2.Argument, null, ref resultList);
    }
    else
    {
        exception = exception2;
    }
}
我不清楚
AppendResult
方法的作用,但我发现:

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

@beatcracker如果在非 终止异常执行应继续执行下一个异常 写入输出为“捕获异常”的指令,并且不久之后 应该退出脚本的命令“exit”

-戴维德·塔莱斯科

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


下面不是一个真正的答案,只是一个想法,希望更熟练的人能从中有所收获。
虽然我不能很好地理解它为什么这样做,但我想我在
System.Management.Automation
assembly(
public class ScriptBlock
)中将它本地化为这段代码:

catch的ScriptBlockforExceptionHandler设置为
true
时,由内部密封类
ExceptionHandlerNode
的方法
Invoke
创建脚本块,该方法从上述公共类
ScriptBlock
调用
CreateExceptionHandler

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;
        }
    }
}
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 };
}
请注意,当
\u isScriptBlockForExceptionHandler
设置为
true
时,当在上面的
InvokeWithPipe
方法中执行catch块时,如果发生异常,则不会引发异常:

catch (ReturnException exception2)
{
    if (!this._isScriptBlockForExceptionHandler)
    {
        ParseTreeNode.AppendResult(contextFromTLS, exception2.Argument, null, ref resultList);
    }
    else
    {
        exception = exception2;
    }
}
我不清楚
AppendResult
方法的作用,但我发现:

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


如果
ParameterArgumentValidationError
是一个非终止异常,那么一切都会正常工作。您必须将其转换为终止异常,例如:
测试函数-param“fasdfsd”-ErrorAction Stop
以获得所需的结果。IIRC使用
-ErrorAction
参数设置错误操作不包括参数错误,因此您必须在此处设置
$ErrorActionPreference='Stop'
。@AnsgarWiechers,是的,刚刚检查过,您是对的,因此
$ErrorActionPreference='Stop'
是唯一的方法。@beatcracker如果在非终止异常后一切正常,则执行应继续执行下一条指令,即写入输出“捕获的异常”,并在应退出脚本的命令“exit”后立即执行。相反,它会写入输出“我不应该被打印”@DavideTalesco是的,它不符合逻辑,但它总是这样工作,请参阅我的“答案”了解详细信息。如果
ParameterArgumentValidationError
是一个非终止异常,那么一切都会正常工作。您必须将其转换为终止异常,例如:
测试函数-param“fasdfsd”-ErrorAction Stop
以获得所需的结果。IIRC使用
-ErrorAction
参数设置错误操作不包括参数错误,因此您必须在此处设置
$ErrorActionPreference='Stop'
。@AnsgarWiechers,是的,刚刚检查过,您是对的,因此
$ErrorActionPreference='Stop'
是唯一的方法。@beatcracker如果在非终止异常后一切正常,则执行应继续执行下一条指令,即写入输出“捕获的异常”,并在命令“exit”后立即退出scrip