How do you know when PowerShell script finished? - wpf

I'm trying to wrap a piece of code into a WPF application so that a user can just hit the button and the code will run. However, because the script can take time to run, I would like to give a status to the end user so that they know it finished. Is there a way to do that with powershell and this style of code posted below?
1..255 | %{
$I = "192.168.2.$_"
Get-MacAddress($I);
function Get-MacAddress {
...
}
}

TL;DR: You can send an exit 1 to exit with a return code of 1 (or any number other than 0), which means it failed for some reason.
Normally (and under specific circumstances) PowerShell scripts exit with a code of 0. Most other applications return an exit code of 0 whenever they are 'successfully completed,' and without any sort of exception or error that the program is consciously aware occurred.
If you're trapping the exit code in the WPF, you could report whether it was successful (exit 0 inserted at some point in your code, or let it finish as expected), or if it failed (exit of any other number) - at which point you would want to consider reporting unique exit codes specific to the reasons that occurred wrong.
Consider also looking into try, catch, and throw as they're quite useful, as well.
EDIT: As a final note, take a good look at how %errorLevel% (where the exit code is stored) is handled under some unique situations. %errorLevel% is what you want to focus on, if you use exit codes.

Related

Script to run multiple OpenCv programs in Windows

I like to run several OpenCV programs one by one in a DO Loop. After searching the web , think for this case need to use batch file. Is that right?
I have 10 OpenCV programs. Each program detect specific features in the image with some successful rate. So, for any image(with many features to be detected) I wonna run first the program with the highest successful rate. If this failed to detect feature then run next one with second highest rate and so on. So, for example program1 is the one with the highest rate, then come program2 and so on
So I have output for each of the 10 OpenCv programs. Let we say output 1 if detect the feature (or the object) in the image and 0 if it failed. So the script should start the program 1 first and if the outcome of this program is 1 then will do something (not important at the moment what), but if the outcome is 0 then need to start the program 2. Same for program 2. If the output of program 2 is 1 then do something (also not important what), but if the output is 0 (means did not detect the object) then run the next program (means program3)
Any idea how it should look like?
I have thinking of something like this , but not sure about the control
#ECHO OFF
START program1.exe
ECHO Timeout waiting for program1.exe to start
GOTO :EOF
:: if the output of program1.exe is 1 then do somethig, else if the output of program1.exe is 0 run the program2.exe (I dont know how this part should be in the script)
:: not sure for control
:startnext
program2.exe
:: or START program2.exe

Retrieve ERRORLEVEL From Executed Script [duplicate]

I have a batch file that calls a VBScript (.vbs) program. After calling it, my batch script checks %errorlevel% to see if the .vbs program failed. I can signal failure with an exit code in the .vbs program with WScript.Quit(1).
However, I can only do that explicitly. If some unexpected run-time error happens, the .vbs quits with an error dialog box, however the exit code is zero so my batch file thinks it suceeded! How can I change that behavior?
And if you are thinking of saying, use on error goto, don't bother... that syntax is available in regular VB, but not in VBScript.
I thought of an out-of-the-box solution... Who says 0 has to mean success? VBScript sometimes returns a 0 return code for failures, so why not embrace that? Adopt 0 as (at least one possible) failure code and make up another number (e.g. 10) as the "success code".
At the end of the script, put WScript.Quit(10). That will only be hit if everything succeeded up to that point. Then instead of "if errorlevel 1" in the calling batch file, use "if %errorlevel% == 10"
EDIT : Having tentatively (see caveats) proposed this, I am rapidly beginning to think that it is a very bad idea, but I leave it here for posterity. The most compelling reason to not use this comes from Eric Lippert at Microsoft, who worked on the design & implementation of VBScript. He states, in answer to another question: VBScript does not make any guarantee that terminators always run. This can mean that this sometimes does not return a non-0 exit code in the case of an unhandled error.
I think I personally will use a 'wrapper batch file that subtracts 1 from the cscript exit code' solution in future.
I like the solution linked to by fmunkert, but I think it requires you to put your code in a particular Class_Initalize, which is clumsy at best. I've devised a related solution that does not require this; you simply "Commit" a successful result at the end of your code; if it's not called, any exception causes the ExitCodeHandler's Class_Terminate instance to set a non-zero exit code.
Option Explicit
Class ExitCodeHandler
private exit_code
Public Sub Commit()
exit_code = 0
End Sub
Private Sub Class_Initialize()
exit_code = -1 ' this exit code will be returned if Commit is never called
End Sub
Private Sub Class_Terminate()
if exit_code<>0 then WScript.Quit(exit_code)
End Sub
Public Sub Quit(exitCode)
Commit
WScript.Quit(exitCode) ' exit code will be respected since we have committed
End Sub
End Class
' create one of these at the start:
Dim ech: Set ech = New ExitCodeHandler
WSCript.StdOut.WriteLine "Hello"
s = "" ' undeclared variable causes runtime error - comment out to see success.
' WScript.Quit(-4) ' before a commit, -1 is returned due to the Class_Terminate
' Commit at the end
ech.Commit
' WScript.Quit(-5) ' after a commit, -5 is returned
Note that this idiom is used heavily in C++, where it is called RAII (Resource Acquisition Is Initialization)
You could of course embellish the class this to support other exit codes, error messages etc. You may want to put this in a common vbs file and use a mechanism for includes in vbscript to share it.
Caveats
I don't know the full details of downsides to calling WScript.Quit during stack unwinding due to an exeption in VBScript. I've disovered the following:
Use with caution. I have come up with this and poked around with it when I saw fmunkert's linked suggestion, not used it extensively.
If you explicitly call WScript.Quit(n), the ExitCodeHandler will replace n with its own exit code. The workaround is to either always call ExitCodeHandler.Commit before calling WScript.Quit, or call the supplied ExitCodeHandler.Quit instead which does it for you. However, relying on either of these methods may not always be practical/possible, and it is fairly non-idiomatic and may not be ovbious to maintainers.
If any other object with a Class_Terminate is terminated (i.e. after ExitCodeHandler's Class_Terminate calls WScript.Quit), you seem to get an error. You may get similar behaviour with any COM objects that are being destroyed. I don't know in what order VBScript destroys objects (or even if it's guaranteed), so I've asked about it in another question.
As you say, all that's available is On Error Resume Next, so your forced to use the pattern:
On Error Resume Next
ThingWithAChanceOfThrowingAnError ...
If (Err.number <> 0) then PrintErrorAndQuitWith1(Err.Description)
You could, if it's an option, use jscript instead which has better support for exception handling, including an easy way to return a non-zero exit code on any exception. See the solution to why does my JScript (windows script host) exit with 0 on an uncaught exception?
This is the #1 reason we're choosing jscript over vbscript (when we have to use one of the two!)
You might use the technique described in this article.
It requires you to wrap your script inside a VBScript class.

Linux compiled binary getting wrong exit code if Ctrl+C entered from a shell script launched by the binary

I've got what I think is a strange one here. I have the following environment.
A Linux compiled binary which sets up a signal handler to disable things like Ctrl+C, Ctrl+z, etc. This is done by calling signal on: SIGINT, SITTSTP and SIGQUIT. The signal handler simply prints an error message that user is not allowed to abort the program.
After setting up the signal handler, the binary calls an interactive ash script.
This interactive ash script ALSO disables all methods of breaking out of the script. It does this with "trap '' INT TSTP" at the very beginning. This works and if one enters Ctrl+C, etc it simply echoes the control character to the terminal but does not exit.
Individually both the binary and ash script prevent user from exiting.
However, notice what happens below:
Allow control to be returned to the binary by normal completion of the interactive shell script. Once control returns to the binary, entering Ctrl+C works and does not allow user to break out of the program. This is proper behavior.
Where it is wrong is:
Type a few Ctrl+C's during the time the interactive shell script is running and once control returns to the binary, the exit code is changed to something other than what the shell script is doing.
Here is an example:
In C code, let's say I have:
void sigintHandler(int sig_num)
{
fprintf(stderr, "You are not allowed to exit this program.\n");
return;
}
void main(void)
{
signal(SIGINT, sigintHandler);
int ret = system("/etc/scripts/test.sh");
printf("test.sh returned: %d exit status.\n", ret);
}
And in test.sh I have:
#!/bin/ash
# Disable interrupts so that one cannot exit shell script.
trap '' INT TSTP
echo -n "Do you want to create abc file? (y/n): "
read answer
if [ $answer == "y" ];then
touch /tmp/abc
fi
if [ -f /tmp/abc ]; then
echo "Returning 1"
exit 1
else
echo "Returning 2"
exit 2
fi
If I run the C binary normally I get the correct exit status (1 or 2) depending on whether file exists. Actually I get 256 or 512 which indicates it is storing the exit code in the 2nd byte. Point is this works consistently every time.
But now if I hit Ctrl+C while the shell script is running (before answering the question presented) and say I answer "n" which is exit code of 2. In the C binary the code I get back is sometimes 2 (not 512, indicating the exit code is now in the LOWER byte) but MORE often I get back a code of 0! This happens even though I see the message "Returning 2" which is echoed by the shell script.
This is driving me nuts trying to figure out why a simple exit code is being messed up.
Can anyone provide some suggestions?
Thanks much
Allen
I found the issue.
Previously I was using trap '' INT TSTP to disable interrupts in the shell script. Though this works to prevent shell script from being aborted it led to the issue in this post. I suspect that in disabling the ability to abort the shell script in this way, the upper level shell framework was not aware of this and all it knew is that Ctrl+C or whatever was pressed and returned SIGINT as the exit code despite what the shell script itself was exiting with.
The solution is to use:
stty -isig
at the beginning of the shell script.
This not only disables interrupts but ALSO lets the upper level framework know that this is what you've done so that it ignores the fact that Ctrl+C was pressed.
I found this information on the following page:
https://unix.stackexchange.com/questions/80975/preventing-propagation-of-sigint-to-parent-process
Thanks everyone,
Allen

How to define a point of crashing in a C software

First : Appologize for my bad english.
Sorry for this newbie software question, but I got lost with my own logic...
A bit background :
I am working on a C networking project, where I am trying to generate a server that receive gradually increasing UDP message within the increasing time. I am trying just to simple "manager" on this server that is able to send a report to a specific address when it is crashing.
The thing that come in mind is that I set this manager as a listener in the server side. So if the server does not receive any message within the predefined port, I assume the server fails.
But, this thing is not -somehow- a deterministic approach. How long should I specify the time if this server crash? (if in 5 minutes no message is received in the port, does it mean it is crashing? not necessarly true. I can again increase it to 10 mins, buat again, this is unjustiable and inconsistent)
I am thinking how an app like gdb can do this. If the server(framework) crash, it will automatically generate a coredump file. I need to do a similar thing like this, so when the framework crash, it will as easy as print a "hello crash". How to create a "manager" on the server that can give me a report if the server crash (using C )
Any idea would be greatly appreciated
Thank you so much
The exit code of a process tells you if a signal caused it to exit. You can write a C program and use wait() to get the exit code or do it in a shell script:
#!/bin/sh
./server "$#"
EXIT=$?
if [ $EXIT -eq 0 ]
then
echo exit success
else
if [ $EXIT -ge 128 ]
then
echo exited with signal $(($EXIT - 128))
else
echo exited with code $EXIT
fi
fi
You could choose to restart the server for the failure case or the signal case.
Most servers rely on careful debugging and do not expect to automatically catch and restart when they crash.

How to detect pending system shutdown on Linux?

I am working on an application where I need to detect a system shutdown.
However, I have not found any reliable way get a notification on this event.
I know that on shutdown, my app will receive a SIGTERM signal followed by a SIGKILL. I want to know if there is any way to query if a SIGTERM is part of a shutdown sequence?
Does any one know if there is a way to query that programmatically (C API)?
As far as I know, the system does not provide any other method to query for an impending shutdown. If it does, that would solve my problem as well. I have been trying out runlevels as well, but change in runlevels seem to be instantaneous and without any prior warnings.
Maybe a little bit late. Yes, you can determine if a SIGTERM is in a shutting down process by invoking the runlevel command. Example:
#!/bin/bash
trap "runlevel >$HOME/run-level; exit 1" term
read line
echo "Input: $line"
save it as, say, term.sh and run it. By executing killall term.sh, you should able to see and investigate the run-level file in your home directory. By executing any of the following:
sudo reboot
sudo halt -p
sudo shutdown -P
and compare the difference in the file. Then you should have the idea on how to do it.
There is no way to determine if a SIGTERM is a part of a shutdown sequence. To detect a shutdown sequence you can either use use rc.d scripts like ereOn and Eric Sepanson suggested or use mechanisms like DBus.
However, from a design point of view it makes no sense to ignore SIGTERM even if it is not part of a shutdown. SIGTERM's primary purpose is to politely ask apps to exit cleanly and it is not likely that someone with enough privileges will issue a SIGTERM if he/she does not want the app to exit.
From man shutdown:
If the time argument is used, 5 minutes before the system goes down
the /etc/nologin file is created to ensure that further logins shall
not be allowed.
So you can test existence of /etc/nologin. It is not optimal, but probably best you can get.
Its a little bit of a hack but if the server is running systemd if you can run
/bin/systemctl list-jobs shutdown.target
... it will report ...
JOB UNIT TYPE STATE
755 shutdown.target start waiting <---- existence means shutting down
1 jobs listed.
... if the server is shutting down or rebooting ( hint: there's a reboot.target if you want to look specifically for that )
You will get No jobs running. if its not being shutdown.
You have to parse the output which is a bit messy as the systemctl doesnt return a different exit code for the two results. But it does seem reasonably reliable. You will need to watch out for a format change in the messages if you update the system however.
Making your application responding differently to some SIGTERM signals than others seems opaque and potentially confusing. It's arguable that you should always respond the same way to a given signal. Adding unusual conditions makes it harder to understand and test application behavior.
Adding an rc script that handles shutdown (by sending a special signal) is a completely standard way to handle such a problem; if this script is installed as part of a standard package (make install or rpm/deb packaging) there should be no worries about control of user machines.
I think I got it.
Source =
https://github.com/mozilla-b2g/busybox/blob/master/miscutils/runlevel.c
I copy part of the code here, just in case the reference disappears.
#include "libbb.h"
...
struct utmp *ut;
char prev;
if (argv[1]) utmpname(argv[1]);
setutent();
while ((ut = getutent()) != NULL) {
if (ut->ut_type == RUN_LVL) {
prev = ut->ut_pid / 256;
if (prev == 0) prev = 'N';
printf("Runlevel: prev=%c current=%c\n", prev, ut->ut_pid % 256);
endutent();
return 0;
}
}
puts("unknown");
see man systemctl, you can determine if the system is shutting down like this:
if [ "`systemctl is-system-running`" = "stopping" ]; then
# Do what you need
fi
this is in bash, but you can do it with 'system' in C
The practical answer to do what you originally wanted is that you check for the shutdown process (e.g ps aux | grep "shutdown -h" ) and then, if you want to be sure you check it's command line arguments and time it was started (e.g. "shutdown -h +240" started at 14:51 will shutdown at 18:51).
In the general case there is from the point of view of the entire system there is no way to do this. There are many different ways a "shutdown" can happen. For example someone can decide to pull the plug in order to hard stop a program that they now has bad/dangerous behaviour at shutdown time or a UPS could first send a SIGHUP and then simply fail. Since such a shutdown can happen suddenly and with no warning anywhere in a system there is no way to be sure that it's okay to keep running after a SIGHUP.
If a process receives SIGHUP you should basically assume that something nastier will follow soon. If you want to do something special and partially ignore SIGHUP then a) you need to coordinate that with whatever program will do the shutdown and b) you need to be ready that if some other system does the shutdown and kills you dead soon after a SIGHUP your software and data will survive. Write out any data you have and only continue writing to append-only files with safe atomic updates.
For your case I'm almost sure your current solution (treat all SIGHUPs as a shutdown) is the correct way to go. If you want to improve things, you should probably add a feature to the shutdown program which does a notify via DBUS or something similar.
When the system shuts down, the rc.d scripts are called.
Maybe you can add a script there that sends some special signal to your program.
However, I doubt you can stop the system shutdown that way.

Resources