PowershellFrameworkCollective/psframework

Add '-Reset' switch parameter to Test-PSFFunctionInterrupt (or add additional function)

Callidus2000 opened this issue ยท 5 comments

While using the FlowControl functions I often stumble over the following problem: I'm using Invoke-PSFProtectedCommand to often ๐Ÿ˜„

simple dummy code:

function Start-Check{
        Invoke-PSFProtectedCommand -Action "Perform Check which fails" -ScriptBlock {
            throw "Check failed" 
        } -Level host -RetryCount 2
        if (Test-PSFFunctionInterrupt) {
            Invoke-PSFProtectedCommand -Action "Perform remediation" -ScriptBlock {
                Write-PSFMessage "Fixed"
            } -Level host -RetryCount 2
            if (Test-PSFFunctionInterrupt) {
                Stop-PSFFunction -Level Error -Message "Problem could not be fixed" -EnableException $true -Tag $Name
            }
        }
}

Scenario is that

  • the first PSFProtectedCommand performs some backend checks (like 'is the server alive?') which uses throw to trigger the retry count
  • The first Test-PSFFunctionInterrupt registers that the checks have failed and
  • uses the second PSFProtecedCommand to fix the problem (like restarting the service)

Problem is that the second Test-PSFFunctionInterrupt returns $true and the complete function stops. It would be great if you could provide a function/parameter to clean the $psframework_killqueue.

You are totally right, that for this kind of flow we need a reset capability.
While some of it could be handled by the -ErrorEvent parameter, there are clear cases where this is not enough.
Added to the backlog for the next release.

Mentioning the -ErrorEvent parameter:
Is there a way to access the error which is causing the ProtectedCommand to fail silently?
I assume from the parameter names like ErrorVariable and ErrorEvent that you've got prepared something for this. But those params (like others) are not included in the detailed command help and I've not yet found out how to achieve my goal...

Access the error

$_

fail silently

Nope, sorry.

ErrorVariable

That's a builtin Parameter that comes with all commands.
Doesn't help here - when Invoke-PSFProtectedCommand fails, it does so with maximum prejudice

But those params (like others) are not included in the detailed command help

Damn, that should not have happened of course.
Will need to update my tests (which should have caught that) and backfill the help for all Cmdlets that slipped through the cracks here (I'm opening a new issue for that so I don't forget).

Anyway, I think the reset capability I'll include in the next release should address your issue.
I'll look into supporting -ErrorAction and -ErrorVariable or alternatives for a natively silent flow, but can't promise anything specific on that front, simply due to the high risk of breaking things or overloading just what this command does.
It has already become quite complex as it is ^^

Access the error

$_

Not working at all or just misunderstood. Example function:

function Invoke-MyScript {
    [CmdletBinding()]
    param (
        [scriptblock]$ScriptBlock,
        [string]$LoggingAction
    )
    Invoke-PSFProtectedCommand -Action $LoggingAction -ScriptBlock $ScriptBlock  -Level host 
    Write-PSFMessage -Level Critical "Accessing the error, Variant 1: $_"
    Write-PSFMessage -Level Critical "Accessing the error, Variant 2: $($Error[0]|Out-String)"
    Write-PSFMessage -Level Critical "Accessing the error, Variant 3: $(Get-Error|Out-String)"
}
$invokeCommandParam = @{
    scriptBlock   = [scriptblock]::Create("`$result = 1 / 0")
    LoggingAction = "Will Fail"
}
invoke-MyScript @invokeCommandParam

Executed I see as a result

  • Variant 1 $_ show noting,
  • Variant 2 and 3 $Error[0] and Get-Error show a desired output.

Runspace Anomaly?

The solution only works if I call the function from the same context, e.g. if I put the above code in a PS1 file and execute it. In my real life scenario the function is provided by a module (based on Invoke-PSMDTemplate -TemplateName PSFProject). If I call the module script function from commandline/script, neither of the three 'Show me the inner error/exception' variants produces any output. Funny thing is that Get-Error called from the command line show the inner exception...

Cost some time to find the cause lies (partly) in providing the function in the module....

Alright, I messed up a little with the error event:
It expects $args[0] there:

function Invoke-MyScript {
    [CmdletBinding()]
    param (
        [scriptblock]$ScriptBlock,
        [string]$LoggingAction
    )
    Invoke-PSFProtectedCommand -Action $LoggingAction -ScriptBlock $ScriptBlock -Level host -ErrorEvent {
		Write-PSFMessage -Level Critical "Accessing the error, Variant 1: $($args[0])"
	}
}
$invokeCommandParam = @{
    scriptBlock   = [scriptblock]::Create("`$result = 1 / 0")
    LoggingAction = "Will Fail"
}
invoke-MyScript @invokeCommandParam

Supporting $_ should still be an option, so I'll see that I add that for the next release.

And no, PSFramework does not expect you to define the scriptblock you run with Invoke-PSFProtectedCommand from outside the caller's context. I am only willing to go so far when hacking the PowerShell system to make my magic happen ^^