Powershell Error Catching With Static Member - powershell

For reasons I'll not get into here, I'm being forced to use powershell to call and then populate a separate application. And to integrate it into a batch file, so powershell -command "& { }", which is already painful. I've got a while loop set call, check for the process ID to come up, then wait and call again if it hasn't come up yet.
The problem here is that afterwards I utilize a static member out of visualbasic to switch the focus to that application.
Namely, [microsoft.visualbasic.interaction]::AppActivate($hwnd) -- where $hwnd is the process ID of the application in question.
I hate to put anything like an artificial timer on there to wait for the application to finish loading, and I'd love to just put a while timer in there. But static member calls don't appear to support -erroraction or -errorvariable -- and the try {} catch {} appears to just ignore the error, as I was hoping to use it to trigger a flag to trigger the while loop to cycle again after a sleep of one second.
What other ways are there to catch errors out of a static member operator ::

Disregard. The Try {} catch {} works great if I don't replace the final bracket with a close parenthesis.

Related

Add_Click function from XAML only parses some commands?

This is an extremely strange issue- I have some Powershell code and a XAML GUI I made with Visual Studio for a fairly basic app for users. I'm fairly experienced with Powershell, but completely new to XAML.
Here's the code snippet:
`
$var_RKH.Add_Click({
$targetSite = $RKH
$var_TargetSite.Content = "Rock Hill"
})
`
Somehow, $targetSite is still null after this click event. I've confirmed the var $RKH contains the needed data. In another click event on another button, I copy-pasted that same line and it works. However, what's absolutely twisted my brain is- the third line works. The $var_TargetSite.Content variable is correctly updated.
So the click event is definitely firing, the second line just gets completely skipped somehow, and the third line works fine. On other click events, the exact same code works fine. I must be missing something very simple because this is absolutely twisting my brain.
Script blocks aren't really scopes. They're script blocks and do not inherit from enclosing scope. Instead, you pass values into it just like you would for a thread in C#. This can get confusing because both scopes and script blocks get the {} delimiter -- they're not the same though and not interchangeable either:
[scriptblock]$Sb = {'This is a test'}
if($true) $sb
will throw a ParserError exception rather than print 'this is a test'.
Please be very careful about "sideloading" variables, especially with WPF; there is a high degree of multithread in any WPF application and you literally don't know who is going to access what when.
If you can, try to resolve the value of $RKH inside the script block rather than try to force it in.
Or you could implement code-behind for the XAML and put both .xaml and .xaml.cs in an assembly, then use that in PS.

PowerShell log all unhandled exceptions

I am looking to log unhandled exceptions, since my script runs as an automated tool with no one monitoring progress at the console. My thinking is to create my own exception class, which has a constructor that accepts [InvokationInfo] so I can then log the error with file and line number info, and possibly the trace stack as well. The goal is to catch as many exception types as possible and handle them, but have a generic final catch for exceptions that are literally my code failing. It occurs to me that the entire script would be one big try/catch so that literally anything I didn't expect (so long as it's terminating) would get caught and logged.
To that end I have this mocked up:
class UnhandledException : Exception {
UnhandledException () : base () {
}
UnhandledException ([System.Management.Automation.InvocationInfo] $InvokationInfo) {
Write-Host "Unhandled Exception in $([System.IO.Path]::GetFileName($InvokationInfo.ScriptName)) at line $($InvokationInfo.ScriptLineNumber)"
}
}
CLS
try {
1/0
} catch [System.IO.IOException] {
# Handled exception types go here
} catch {
$unhandledException = [UnhandledException]::new($PSItem.InvocationInfo)
#throw $unhandledException
}
This seems to be working well, and I am debating if that final throw is needed, or if I can just as well terminate the script from within the exception, since by definition once I have logged that info, and maybe thrown up toast message about the failure, I will be exiting the script anyway.
My question is, is this an appropriate way to handle exceptions when the script is functioning as a silent command line utility? I really don't want to have a situation where, if the console is showing, that powershell exceptions are visible. I want to handle everything, to the extent I can, quietly and with log files. Those logs could then be sent to me so I could troubleshoot.
That said, I have not found any info on wrapping the entire script in a try/catch. This
suggests that "catch everything" is a code smell, but it's also talking more about methods that are consumed by other users, not utility scripts.
The bit about std::uncaught_exception() sounds like it might be an option too, if I could have my regular log, for logging actual progress of the script and error in data, inability to access network resources, etc. All of which would be exceptions that I do catch and handle. If I could define a log file that is ONLY for otherwise uncaught exceptions that might be even better, but I also haven't found anything like that for PowerShell. So my approach is my backup plan. Unless I am missing something and this is a horrible idea?
And, to be clear, I am not thinking this would be the ONLY exception handling. This would be the handler of last resort, logging anything that I hadn't otherwise expected, planned for and handled.
EDIT: So, a limitation I have found to trap is that it still only traps terminating errors, and ideally I would like to also get a log of continued errors as well. To that end, I have been exploring redirects I have tried this
function LocalFunction {
1/0
}
&{
CLS
LocalFunction
Remove-Item 'Z:\no.txt' -errorAction silentlyContinue
Test-Path 'C:\'
Write-Host 'Continued'
} 2>> c:\errors.txt
This will successfully log the divide by 0 error in the function and the error at Remove-Item when -errorAction is Continue (the default), but when I specially set it to SilentlyContinue it isn't logged. This seems to get me where I want to be, with ANY error that would be seen in the console instead going to the text file. I could then, at the end of processing, test the size of that file, and delete if 0 or provide a toast message if something got logged.
The real question becomes, is the &{} construct around basically the entire script a viable option once it's a 10,000 line script, rather than a little example? And is it a good idea in general? Or is this perhaps something useful during development, but I just need to put on my big boy pants and actually HANDLE every possible error?
EDIT 2: Well, after doing some tests on a branch of my utility, this redirect approach is actually looking REALLY promising. Apparently no impact on performance, and I can even add the contents of my errors log to my regular log to make things easier for users. Curious if anyone has some counter indications?
Also, a little digging suggest that Invoke-Expression might be better, because the & operator creates a child scope, and that might cause problems while Invoke-Expression doesn't. But on the other hand Invoke-Expression is right up there with Regular Expressions in the "Don't do that" hierarchy. Things that make you go hmmmmmm?

Can a matlab function called within a script cause the script to break?

I am running a script which calls a function, and if a certain condition is met, inside the function, I want the whole thing just to terminate (and by that I do not mean I want to close matlab using exit). Is that possible? I know I can use return or break to return to the script, however I want the script to stop as well if this condition is met.
The only function I know of that does this is error. This throws an exception, and, if no exception handlers with try and catch are installed in the calling script, will terminate and return to command prompt. Which is what you want, as far as I understand. It prints an error message though. This could be suppressed if you guard all code in the top-level script with a try catch handler. However this will have to be specific to the one error and it makes debugging ("stop-on-error") much more difficult.
The thing is that the only use case I see for this behavior (termination of whole program on certain event) is when a non recoverable error occurs, and in that case printing an error message is indeed appropriate.
In case the script is successful termination of the whole program is not really the right way. All functions should return to give the upper layers of the code to perform some clean-up action, like saving the output data or so.

Powershell script “on exit” event?

Instead of calling a function at the end of all scripts to perform cleanup tasks, I'm looking to register for an 'on return' event for when the script (not the PowerShell session) is finished.
A script can return at various points though (eg, no records to process), so the current situation is problematic.
Register-EngineEvent applies to the PowerShell session, and operators run scripts manually, thus it's problematic.
I can't find a list of built-in powershell events or an alternative solution.
#Vesper wrote it as a comment, but a try/finally block is definitely what I would suggest for this:
try {
# some code
} finally {
# this gets executed even if the code in the try block throws an exception
}

Suspending the workflow instance in the Fault Handler

I want to implement a solution in my workflows that will do the following :
In the workflow level I want to implement a Fault Handler that will suspend the workflow for any exception.
Then at sometime the instance will get a Resume() command .
What I want to implement that when the Resume() command received , the instance will execute again the activity that failed earlier ( and caused the exception ) and then continue to execute whatever he has to do .
What is my problem :
When suspended and then resumed inside the Fault Handler , the instance is just completes. The resume of course doesn't make the instance to return back to the execution,
since that in the Fault Handler , after the Suspend activity - I have nothing. So
obviously the execution of the workflow ends there.
I DO want to implement the Fault Handler in the workflow level and not to use a While+Sequence activity to wrap each activity in the workflow ( like described here:
Error Handling In Workflows ) since with my pretty heavy workflows - this will look like a hell.
It should be kinda generic handling..
Do you have any ideas ??
Thanks .
If you're working on State Machine Workflows, my technique for dealing with errors that require human intervention to fix is creating an additional 'stateactivity' node that indicates an 'error' state, something like STATE_FAULTED. Then every state has a faulthandler that catches any exception, logs the exception and changes state to STATE_FAULTED, passing information like current activity, type of exception raised and any other context info you might need.
In the STATE_FAULTED initialization you can listen for an external command (your Resume() command, or whatever suits your needs), and when everything is OK you can just switch to the previous state and resume execution.
I am afraid that isn't going to work. Error handling in a workflow is similar to a Try/Catch block and the only way to retry is to wrap everything is a loop and just execute the loop again if something was wrong.
Depending on the sort of error you are trying to deal with you might be able to achieve your goal by creating custom activities that wrap their own execution logic in a Try/Catch and contain the required retry logic.