How to pass integers and strings from MATLAB to a PowerShell script? - powershell

I need to automate a test. The test itself is being written (by me) in MATLAB, has 5 stages, each stage ends with setting a value to an integer (uint16_t and uint8_t) and with a message. I have to pass these 5 integers and 5 strings to a PowerShell script because Jenkins can only run a PowerShell or Python script, but I'm not entirely sure how can I achieve that. I have never used PS or done any scripting, and there isn't much on the Internet on how to even run a MATLAB script with PowerShell. (Maybe I should check batch file scripts running MATLAB scripts.)
The only option I've found so far is writing into a (temporary) file with MATLAB, then reading from it (and deleting it), it could be a .txt file, or preferably a .csv file (although using csvwrite is not recommended by Mathworks), but this isn't very reliable. Can anyone suggest other methods to pass it more directly? The MATLAB file is not a function, but it can be made to be one that has these variables as outputs. Also, it's fine if the integers are cast to another integer type.

Like #TessellatingHeckler said the way is $results = matlab.exe yourscript.
Here is an example if you want more features when launch the tests like no display windows ,run in a batch mode or wait to the end of matlab execution.
runTestMatlab (){
result=$(matlab.exe -wait -nosplash -noFigureWindows -batch TestScript.m)
if [ $? -ne 0 ]; then
# Error with the Matlab run
echo $result
return 1
fi
echo "$result"
return 0
}
Then you can parse the result with awk or any other tool that you want.

Related

Manage inputs from external command in a powershell script

First, I would like to apologize in case that the title is not descriptive enough, I'm having a hard time dealing with this problem. I'm trying to build an automation for a svn merge using a powershell script that will be executed for another process. The function that I'm using looks like this:
function($target){
svn merge $target
}
Now, my problem occurs when there are conflicts in the merge. The default behavior of the command is request an input from the user and proceed accordingly. I would like to automatize this process using predefined values (show the differences and then postpone the merge), but I haven't found a way to do it. In summary, the workflow that I am looking to accomplish is the following:
Detect whether the command execution requires any input to proceed
Provide a default inputs (in my particular case "df" and then "p")
Is there any way to do this in powershell? Thank you so much in advance for any help/clue that you can provide me.
Edit:
To clarify my question: I would like to automatically provide a value when a command executed within a powershell script require it, like in the following example:
Requesting user input
Edit 2:
Here is a test using the snippet provided by #mklement0. Unfortunately, It didn't work as expected, but I thought it was wort to add this edition to clarify the question per complete
Expected behavior:
Actual result:
Note:
This answer does not solve the OP's problem, because the specific target utility, svn, apparently suppresses prompts when the process' stdin input isn't coming from a terminal (console).
For utilities that do still prompt, however, the solution below should work, within the constraints stated.
Generally, before attempting to simulate user input, it's worth investigating whether the target utility offers programmatic control over the behavior, via its command-line options, which is both simpler and more robust.
While it would be far from trivial to detect whether a given external command is prompting for user input:
you can blindly send the presumptive responses,
which assumes that no situational variations are needed (except if a particular calls happens not to prompt at all, in which case the input is ignored).
Let's assume the following batch file, foo.cmd, which puts up 2 prompts and echoes the input:
#echo off
echo begin
set /p "input1=prompt 1: "
echo [%input1%]
set /p "input2=prompt 2: "
echo [%input2%]
echo end
Now let's send responses one and two to that batch file:
C: PS> Set-Content tmp.txt -Value 'one', 'two'; ./foo.cmd '<' tmp.txt; Remove-Item tmp.txt
begin
prompt 1: one
[one]
prompt 2: two
[two]
end
Note:
For reasons unknown to me, the use of an intermediate file is necessary for this approach to work on Windows - 'one', 'two' | ./foo.cmd does not work.
Note how the < must be represented as '<' to ensure that it is passed through to cmd.exe and not interpreted by PowerShell up front (where < isn't supported).
By contrast, 'one', 'two' | ./foo does work on Unix platforms (PowerShell Core).
You can store the SVN command line output into a variable and parse through that and branch as you desire. Each line of output is stored into a new enumerator (cli output stored in PS variables is in array format)
$var = & svn merge $target
$var

same input for interactive command in Perl script

In Perl script I am using command of unit(external command) using system
but that command need some run time input from user. Every time I want to give similar input which is stored in variable.
My command is:
system("dt ci $dest_file");
after this command my script is waiting for user input,
lets say I want to give "re base" as input to this every time
How can I give fix input every time it asks?
Please help, I am working on windows 7.
I want to make script completely automated... it should not wait for user input
If you call your script like this:
perl test.pl < input.txt
It should take the content of the file as an input. ( this is working with STDIN read )

Returning data from .Net EXE to Powershell

I have a powershell script that calls an executable to do some data crunching and the script needs to retrieve the results from by the executable file. Wondering what options I have on plate for this inter process communication
Can I have the executable file directly return a string array or an object (I don't think this is possible)?
Volatile variable that the exe file sets and the powershell script reads from?
Spawn a temporary .Net remoting server within the executable and have the powershell ping that server to get the results
You could just spit out the results from the EXE to stdout in XML or CSV format and have PowerShell slurp it up with either a cast to [xml] or ConvertFrom-Csv.
That the executable is written in .NET makes no difference: it will be a separate process and therefore only the mechanisms for passing data from one process to another (without specific support in both) are available:
The return value from the exe: an integer.
Standard output from the exe: a string (usually divided into separate lines by splitting on newlines and thus treated as an array).
(Theoretically standard error could also be used, but that would be abusing it for no additional functionality.)
The standard output approach is easiest: in the exe use Console.WriteLine (which is a shortcut to Console.Out.WriteLine) and then parse the strings in PowerShell:
MyExe | Foreach-Object {
# Do something with $_ which will be a string
}
Obviously any data format that can be encoded into strings can be used. Also the calling script could accumulate the whole output into a single value and process it all at once.

Running a matlab program with arguments

I have a matlab file that takes in a file. I would like to run that program in the matlab shell, such as prog. I need to implement it so that it takes a number of arguments, such as "prog filename.txt 1 2 which would mean that i can use filename.txt and 1 2 as variables in my program.
Thank you!
In order to make a script accept arguments from the command line, you must first turn it into a function that will get the arguments you want, i.e if your script is named prog.m, put as the first line
function []=prog(arg1, arg2)
and add an end at the end (assuming that the file has only one function). It's very important that you call the function the same name as the file.
The next thing is that you need to make sure that the script file is located at the same place from where you call the script, or it's located at the Matlab working path, otherwise it'll not be able to recognize your script.
Finally, to execute the script you use
matlab -r "prog arg1 arg2"
which is equivalent to calling
prog(arg1,arg2)
from inside Matlab.
*- tested in Windows and Linux environments
Once your function is written in a separate file, as discussed by the other answer you can call it with a slightly more complicated setup to make it easier to catch errors etc.
There is useful advice in this thread about ensuring that Matlab doesn't launch the graphical interface and quits after finishing the script, and reports the error nicely if there is one.
For example:
matlab -nodisplay -nosplash -r "try, prog(1, 'file.txt'), catch me, fprintf('%s / %s\n',me.identifier,me.message), exit(1), end, exit(0)"
The script given to Matlab would read as follows if line spaces were added:
% Try running the script
try
prog(1, 'file.txt')
catch me
% On error, print error message and exit with failure
fprintf('%s / %s\n',me.identifier,me.message)
exit(1)
end
% Else, exit with success
exit(0)

suppress start message of Matlab

I want to call matlab in bash non-interactively and use its result outside Matlab.
For example, I have a script test.m
rand(3,4)
quit
When I execute in bash
$ matlab -nosplash -nodesktop -nodisplay -r test
Warning: No window system found. Java option 'MWT' ignored
< M A T L A B (R) >
Copyright 1984-2008 The MathWorks, Inc.
Version 7.7.0.471 (R2008b)
September 17, 2008
To get started, type one of these: helpwin, helpdesk, or demo.
For product information, visit www.mathworks.com.
ans =
0.8147 0.9134 0.2785 0.9649
0.9058 0.6324 0.5469 0.1576
0.1270 0.0975 0.9575 0.9706
Is it possible to suppress the start message of Matlab and only show the results also without "ans=".
Note I am asking a general question not just for this example.
Thanks and regards!
Try using the -logfile command line option:
-logfile log - Make a copy of any output to the command window
in file log. This includes all crash reports.
Then you can easily remove the first few lines using any way you want (sed for example). Example:
matlab.exe -nosplash -nodesktop -nojvm -logfile out.log -r 'rand(3,3), exit'
sed '1,5d' out.log
Also if you are running from a script where you need it to finish running before continuing, use the -wait option:
-wait - MATLAB is started by a separate starter program
which normally launches MATLAB and then immediately
quits. Using the -wait option tells the starter
program not to quit until MATLAB has terminated.
This option is useful when you need to process the
the results from MATLAB in a script. The call to
MATLAB with this option will block the script from
continuing until the results are generated.
More info on MATLAB startup options can be found here, or in the matlab executable reference pages: Windows/Unix
You could use the Unix command "tail +n" to remove the first n lines of output. That header looks like 10 lines, so this will strip it.
$ matlab -nosplash -nodesktop -nodisplay -r test | tail +10
This is a little fragile, though, since warnings (like that "no window system") will get stripped, and the header size will vary depending on what warnings happen (and those warnings are useful diagnostics). Also, that warning might be on STDERR instead of STDOUT, so "tail +9" might be what you need.
A more robust approach could be to modify the Matlab script to write to a separate file using fopen/fprintf/fclose. That way the header, warnings, errors, etc from Matlab will be separated from the formatted output you want. To get the "disp" output to go to that separate file handle, you can capture it using evalc. The outfile could be specified using an argument to test() in the -r message, and the $$ env variable (the bash process's PID) incorporated in the file name to prevent collisions in a multiprocess environment.
function test(ppid)
outfile = sprintf('outfile-%d.tmp', ppid);
fh = fopen(outfile, 'w');
myvar = rand(3,4);
str = evalc('disp(myvar)');
fprintf(fh, '%s', str);
fclose(fh);
To invoke it from bash, use this calling form. (May be minor syntax problems here; I don't have a Unix box to test on right now.)
% matlab -nosplash -nodisplay -r "test($$)" -logfile matlab-log-$$.tmp
Let's say your bash PID is 1234. Now you've got your output in outfile-1234.tmp and a Matlab log in matlab-log-1234.tmp. Stick them in /tmp if you don't want to be dependent on pwd. You could extend this to create multiple output files from a single matlab invocation, saving the startup costs if you need to compute multiple things.
I'd recommend saving the output to a file, and then reading in that file. This approach is slightly more complicated, but less fragile as formats change etc. It gives you much more control. You'll find plenty of scripts on the web to transform Matlab files to a different host language.
Example:
A = randn(3, 2);
save temp_output.mat A
# Later, read temp_output.mat in whichever language you desire.
To suppress the display of ans =, you can use the DISP function:
disp(rand(3,4));
To suppress that first warning message, you can try adding in the option -nojvm to see if that helps.
To suppress everything else, you can try this solution from a MathWorks Newsgroup thread that addresses the same problem.
Calling MATLAB like this
matlab -nodisplay <test.m &>matlab.output
will dump all of the startup messages and other displayed output into the matlab.output file (which can be named anything you want). If you then (following Peter's suggestion) have test.m save the result that you need to a file using
csvwrite('temp_output.txt',A)
or another appropriate output function you can then read in this file and proceed.