Run octave script from powershell and wait for it to finish - powershell

I'm trying to run a very simple octave .m file from Powershell but i can't manage to make powershell wait for it to finish. In fact, it launches the script execution but then immediatly starts executing the next line.
As I said the script is really simple, just a test
a=100
% Saving just to be sure that the script excuted
save test.mat a
% Pausing to be sure that the execution is not too fast
pause(10)
disp("no way")
And in powershell I simply run
octave --persist test.m
but prompt doesn't wait for octave to finish execution. It seems somehow it runs it async in another process.
I've tried running the script from batch with the wait option
START /W octave --persist test.m
but the result still the same.
Thanks in advance
EDIT 1
Thanks to #Trey Nuckolls I'm using this patch:
$Donefilename = 'done'
if (Test-Path $Donefilename) {
Remove-Item $Donefilename
Write-Host "Last execution $Donefilename has been deleted"
}
else {
Write-Host "$Donefilename doesn't exist"
}
octave --persist test.m
do{
$i++
Start-Sleep -Seconds 2
$OctaveComplete = Test-Path -Path $Donefilename
}
until ($OctaveComplete -or ($i -eq 30))
Making the octave script writing an empty "done" file at the end of execution. Not the best solution although; I'm not able to redirect the execution output for example.
EDIT 2
So, i managed to find the problem thanks to all your responses and comments. It seems that when i was calling octave from windows it wasn't calling the executable but something else. Getting the right path and executing:
& "C:/Program Files/GNU Octave/Octave-6.4.0/mingw64/bin/octave-cli.exe" test.m
works perfectly (you need just to add exit at the end of the script). So, it was a matter of path.

You might consider putting a wait loop into your invoking script like...
do{
$i++
Start-Sleep -Seconds 10 #Assuming that 30 seconds is way too long
$OctiveComplete = <**Boolean returning function that becomes 'True' when run is complete**>
}
until ($OctiveComplete -or ($i -eq 4))
This would go directly after the line that invokes Octave.

Related

How can you keep a Powershell script running continuously with TaskScheduler?

I have a (dumbed down for here) Powershell script that I want to run when a user logs in (actually through auto login) that I want it to be always running.
$i = 0
$max = 5
$f = "D:\VirtualBox-Powershell\out.txt"
do {
$i += 1
Add-Content -Path $f -Value $((Get-Date).ToString())
Start-Sleep -Seconds 1
}
while ($i -lt $max)
exit $i
Yes, I’m aware this will stop after 5 seconds. My actual code is in a continuous loop. I’m using TaskScheduler to start my script after login. Theoretically that should be enough. But the script stops for some unknown reason. It’s either a bug in the script or something else is killing the process.
So I added a trigger to attempt to run the script every minute (which for testing purposes 5 seconds is plenty). When I right click my task and select Run, the script sure enough modifies the file. The task shows running and after 5 seconds I refresh and it shows ready.
But when the trigger fires (the last Run Time shows it started at the correct time), and I refresh it immediately shows Ready.
In both runs the exit code is Ox 1
I’ve tried starting the script by running the ps1 file directly, as well as using C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe and passing in the script as a parameter.
I’ve had some form of this issue for years, and have never found a decent workaround. I’m hoping someone here does.
Windows 10, btw

How to break out of script using invoke-expression

I have a powershell script that works like a menu. After making a choice, it starts another powershell script.
The other scripts are fairly large, and I have many points in the scripts where I need to abort that script and return back to the menu.
I call the other scripts using:
invoke-expression -Command "& '.\script.ps1'"
In the script itself, at various locations, I use the following command to break out of the script.
break script
This works well, as it terminates the script, but it does not return to the previous invoked script.
The break command with parameter means that it breaks to a label. If no label is present it will break out of the entire script. But given how I invoke the script currently, it sees everything as one big script and breaks out of everything.
In my subscript, I placed the following at the end of the file:
:End_Of_Script
and used break End_Of_Script but that fails the same.
So my question is boiling down to this:
How can I invoke another script and at any point break out of that script and return back to the previous script without altering the complete structure of that script?
Here's a snippet of what the subscript is:
write-host "1. Choice A"
write-host "2. Choice B"
$choice = read-host "What choice?"
switch ($choice)
1
{
write-host "The choice is A"
}
2
{
write-host "The choice is B"
}
default
{
write-host "Invalid choice"
break script
}
get-childitem | foreach-object {
if( $_.Name -like "*test*")
{
break script
}
}
In my main script, the commands after invoke-expression ... are never executed.
You can use exit to do this.
The exit keyword is best used in functions, and when those functions are called in a script. It's a great way to terminate execution of functions.
reference PowerShell Exit Function & Code Execution | Pluralsight
If the script encounters an error and needs to exit, throw can be used to better prompt the specific cause of the error.
Calling another script can be done with & $FilePath, invoke-expression -Command "& '$FilePath'" is a cumbersome and unnecessary usage.

Powershell conditionals

I would like to write this in powershell but can not seem to get it to work no matter how I try it. I've used "try and catch" but it doesn't seem to work the way I want.
Try
{
write-host Attempting Reset
CD C:\MKC1_ECU_Reuse
./power_on.bat
CD C:\UTIL\XDL\XMIT\BIN
.\xpc32_nodriver conm2.xpc -con
.\xpc32_nodriver $global:path\$global:customer\$global:customer_reset.xpc
}
Catch
{
Write-warning "Something went wrong!: $_"
return # script failed
}
In Batch, it would look like this:
Do some task || goto :error
goto :finished
Powershell will try to do the task and then go to the next line regardless of if the task completed successfully. The task I am trying to do is to connect to an EEPROM and write to it. If the write fails, I do not want to continue my script. I would rather be able to display an error telling the operator that there was an issue. I am working with what my company allows me to work with or I would use the newest Powershell that allows for || and &&. Any help would be appreciative.
Inside the batch file you may need something like:
IF %ERRORLEVEL% NEQ 0 (
exit %ERRORLEVEL%
)
That should relay the elevated exit code back to PowerShell in the $LASTEXITCODE variable. Then you may be able to use the logic from the previous answer.
I guess they are forcing you to use .bat, but it might be better is you launched the underlying program from inside PowerShell.
Try/Catch only works with teminating powershell command errors. You can test
if ($LASTEXITCODE -ne 0) or if (-not $?) for an error.
Taking a guess at an answer:
$result = .\xpc32_nodriver $global:path\$global:customer\$global:customer_reset.xpc
if ($result -like '*error*') {
write-warning 'Something went wrong!'
exit 1
}

running a command repeatedly on a remote server

I wrote the following script to run a command on a remote server with 5 sec interval. The command inside $LogrCmd variable runs on a remote server to check if a particular service is up or down. I expect the script to poll the service every 5 seconds until the service is completely down. However the scripts exits out immediately even if the service is up.
$LogrCmd = get-content 'c:\temp\info.cfg' | select-string -Pattern cheetahdev
while (-not (Invoke-Command -ScriptBlock {& cmd.exe /c "$LogrCmd"})) {
## Wait a specific interval
Start-Sleep -Seconds 5
}
Here's the contents of the info.cfg file which runs against the remote host.
"C:\PWX\pwxcmd displaystatus -sv cheetahdev"
You would do better to use a do / while loop here instead of a while loop:
$LogrCmd = Get-Content 'c:\temp\info.cfg' | Select-String -Pattern cheetahdev
do {
cmd.exe /c "$LogrCmd"
## Wait a specific interval
Start-Sleep -Seconds 5
} while ( $LASTEXITCODE -eq 0 )
This will always run the command once, sleep, then check to see if the command succeeded. If the command succeeded it will continue the loop. Of course, you can tailor the while condition to check for other exit codes and conditions as well.
Note that for external commands it's best to rely on $LASTEXITCODE most of the time to check for command success, unless you need to parse the output of the command or something else less common.
Also note that by reading the full command from the file like that opens you up to code injection attacks by someone familiar with how to manipulate your info.cfg.

How to keep a powershell script running 24/7

I have a PowerShell script that needs to be restarted when it dies for whatever reason, be it a crash, a self exit or after a system reboot...
How can I, from a bat or another powershell script, see to it that if it is not running, it will be started again...
i.e. how can I find out if it is already running from another script?
I know I can make one powershell script start the active one and simply have it loop a new start as long as it doesnt exit with a specific error... but then THAT scripts need to be seen to :D So we are back to the original quesiton, how do I keep THAT script running 24/7?
do
{
$date = Get-Date -format "yyyy-MM-ddTHH:mm:ss"
"$($date) Repeat : Restarting Worker, LastExitCode $($LastExitCode)." | Out-File D:\IDM\Worker\Worker.LOG -width 180 -append
powershell -File "D:\IDM\Scripts\Worker.ps1"
sleep 10
}
while ($LastExitCode -ne $null)
I would just use scheduled tasks. There are plenty of options in there to help you do what you want. You can run the script every five minutes and have it do enough loops to take up that time and quit:
$now = Get-Date
while ($now.AddMinutes(5) -lt (Get-Date)){
...work...
}
Or you could even have it write a flag file every time the loop works and have any new process check that file to see if there hasn't been activity on it. If there's been no activity:
$workFlag = Get-Item C:\work.flg
$cutOff = (Get-Date).AddMinutes(-5)
if ($workFlag.LastWriteTime -gt $cutOff){
New-Item -force -path C:\work.flg
...work loop..
}