I am receiving data from serial port. I use HWUT for comparing my test results. The content from receive buffer cannot be directly used for comparison of GOOD and OUT result. Becuase the OUT will always have unnecessary command prompts, enters and other stuff. I am looking to select what must be written from read buffer into OUT file. For example below is an example
←[36m
A> target cmd
←[36m
{t=3883.744541 s} Received data
A> result : 1
bytes read 518Closing serial port...OK
And I would like the out file to only have 'result : 1'.
When i checked the code, messages.py seems to be printing to std out. But not sure if that is being used for printing into OUT file. How can this be achieved?
Anything that you print to 'stdout' should appear in the "OUT/*" files. If it does not, then this would have nothing to do with receiption via serial line(s). Here is what I would do to analyze:
In your connector application there must be something like
receive_n = receive(.., &buffer[0], Size);
buffer[receive_n] = '\0'; /* terminating zero */
printf("%s", &buffer[0]);
If this is so, then
Write in paralell into a log file.
static log_fh = fopen("tmp.log", "wb");
...
printf("%s", &buffer[0]);
fwrite((void*)buffer, 1, received_n, log_fh);
Compare 'tmp.log' with the file in OUT.
If there is a difference, HWUT is to blame.
Check the output before you write it.
if( my_condition(buffer, received_n) ) printf("%s", &buffer[0]);
HWUT has an internal infrastructure to post-process test output, but it is not documented and therefore not reliable--at the time of this writing.
Edit the file "hwut-info.dat" in your TEST directory.
These R my Tests on Something Important (Title)
-------------------------------------------------------
--not *.exe
bash execute-this.sh
-------------------------------------------------------
The --not *.exe makes sure that HWUT will not execute the *.exe files which you compiled. The bash execute-this.sh line lets HWUT consider the file execute-this.sh as a test application and call it with 'bash'.
Inside the execute-this.sh you might want to make your application, execute it and filter the output, i.e.
#! bash
make my-test.exe
./my-test.exe | awk ' /^A>/ '
which will print only those lines which start with 'A>'. grep and awk are your friends, here. You might want to familiarize yourself with these two.
Alternatively, you may filter directly in your connection application.
Related
I have a Fortran program that starts with opening and reading data from a .txt file.
At the end of the program a new file is written, which replaces the old file (that was originally imported).
However it can occur that the file that needs to be opened does not exists, for that case the variables that should be imported from the .txt file should be 0.
I thought by doing this with the code below, however this does not work and the script is aborted when the file history.txt does not exists.
How can I let the script set default values to my variables when the history.txt file does not exists?
OPEN(UNIT=in_his,FILE="C:\temp\history.txt",ACTION="read")
if (stat .ne. 0) then !In case history.txt cannot be opened (iteration 1)
write(*,*) "history.txt cannot be opened"
KAPPAI=0
KAPPASH=0
go to 99
end if
read (in_his, *) a, b
KAPPAI=a
KAPPASH=b
write (*, *) "KAPPAI=", a, "KAPPASH=", b
99 close(in_his)
The file that is imported is pretty simple and looks like:
9.900000000000006E-003 3.960000000000003E-003
I would use IOSTAT as stated by #Fortranner. I would also set defaults before trying to open the file and I tend not to use goto's. As in:
program test
implicit none
integer :: in_his, stat
real :: KAPPAI, KAPPASH
in_his = 7
KAPPAI = 0
KAPPASH = 0
OPEN(UNIT=in_his, FILE="history.txt",ACTION='read',IOSTAT=stat,STATUS='OLD')
if (stat .ne. 0) then
write(*,*) "history.txt cannot be opened"
stop 1
end if
read (in_his, *) KAPPAI, KAPPASH
close(in_his)
write (*, *) "KAPPAI=", KAPPAI, "KAPPASH=", KAPPASH
end program test
Another way is to use an inquire statement and check for the existence of the file before you try to open it. This would set a logical variable that could be used in an IF statement to handle the two cases: 1) open file and read values, or 2) set default values w/o opening the file. Or set the default values first, then have the IF statement only handle the case of opening the file and reading the values.
Set iostat in the open statement and handle the case where it is nonzero.
There are two ways to do this. One is using IOSTAT specifier in the OPEN statement like Fortranner and Timothy Brown suggested. The other is to use the ERR specifier in the OPEN statement which lets you specify a label to which the program will transfer control in the even of an error:
OPEN(UNIT=in_his,FILE="C:\temp\history.txt",ACTION="read",STATUS='OLD',ERR=101)
...
101 CONTINUE
The label must be in the same scoping unit as the OPEN statement.
I'm trying to call a perl script from another perl script, read from serial port, and write to a file. I've distilled my code to isolate the problem, so it probably won't make sense what the point of the code is.
Caller:
use Win32::Process;
my $perl_path = $^X;
my $SerialLogProcess;
my $SerialLogObj;
my $serial_log_script = "callee.pl";
Win32::Process::Create($SerialLogObj, "$perl_path", "perl $serial_log_script " ,0,NORMAL_PRIORITY_CLASS,".");
$SerialLogProcess = $SerialLogObj->GetProcessID();
print "waiting for 3 secs";
sleep(3);
print "done";
`taskkill /F /T /PID $SerialLogProcess`;
Callee:
use Win32::SerialPort;
my $portObj = new Win32::SerialPort("\\\\.\\COM70") || die;
my $serialReading;
$portObj->baudrate(115200);
$portObj->parity("none");
$portObj->databits(8);
$portObj->stopbits(1);
system("rm -r \"log.txt\"");
open (LOGFILE, ">>log.txt") or die;
while (1){
$serialReading = $portObj->read(10);
print LOGFILE $serialReading;
#print LOGFILE " ";
}
So the caller creates a process for the callee script, and then kills it after 3 seconds. In those 3 seconds, I do something that gives guaranteed messages for the serial port to read. The log file is created, but nothing is written to it.
Heres what's weird: I can make the messages show up two ways. I run the callee script straight from the command line, or I can uncomment that last print. Unfortunately, these aren't solutions for me. I'm pretty stumped why I can't get my code to work properly, and it makes me think there is some kind of undefined behavior.
The output is buffered by default. The data will eventually be written once there's enough to write. Or you can use the following which will cause a flush for every print.
use IO::Handle qw( ); # Needed before Perl 5.14
open (LOGFILE, ">>log.txt") or die;
LOGFILE->autoflush(1);
But ug, why use a global variable???
open (my $LOGFILE, ">>log.txt") or die;
$LOGFILE->autoflush(1);
print $LOGFILE $serialReading;
I have a file called backup.lua, which the program should write to every so often in order to backup its status, in case of a failure.
The problem is that the program writes the backup.lua file completely fine first-time round, but any other times it refuses to write to the file.
I tried removing the file while the program was still open but Windows told me that the file was in use by 'CrysisWarsDedicatedServer.exe', which is the program. I have told the host Lua function to close the backup.lua file, so why isn't it letting me modify the file at will after it has been closed?
I can't find anything on the internet (Google actually tried to correct my search) and the secondary programmer on the project doesn't know either.
So I'm wondering if any of you folks know what we are doing wrong here?
Host function code:
function ServerBackup(todo)
local write, read;
if todo=="write" then
write = true;
else
read = true;
end
if (write) then
local source = io.open(Root().."Mods/Infinity/System/Read/backup.lua", "w");
System.Log(TeamInstantAction:GetTeamScore(2).." for 2, and for 1: "..TeamInstantAction:GetTeamScore(1))
System.LogAlways("[System] Backing up serverdata to file 'backup.lua'");
source:write("--[[ The server is dependent on this file; editing it will lead to serious problems.If there is a problem with this file, please re-write it by accessing the backup system ingame.--]]");
source:write("Backup = {};Backup.Time = '"..os.date("%H:%M").."';Backup.Date = '"..os.date("%d/%m/%Y").."';");
source:write(XFormat("TeamInstantAction:SetTeamScore(2, %d);TeamInstantAction:SetTeamScore(1, %d);TeamInstantAction:UpdateScores();",TeamInstantAction:GetTeamScore(2), TeamInstantAction:GetTeamScore(1) ));
source:close();
for i,player in pairs(g_gameRules.game:GetPlayers() or {}) do
if (IsModerator(player)) then
CMPlayer(player, "[!backup] Completed server backup.");
end
end
end
--local source = io.open(Root().."Mods/Infinity/System/Read/backup.lua", "r"); Can the file be open here and by the Lua scriptloader too?
if (read) then
System.LogAlways("[System] Restoring serverdata from file 'backup.lua'");
--source:close();
Backup = {};
Script.LoadScript(Root().."Mods/Infinity/System/Read/backup.lua");
if not Backup or #Backup < 1 then
System.LogAlways("[System] Error restoring serverdata from file 'backup.lua'");
end
end
end
Thanks all :).
Edit:
Although the file is now written to the disk fine, the system fails to read the dumped file.
So, now the problem is that the "LoadScript" function isn't doing what you expect:
Because I'm psychic, i have divined that you're writing a Crysis plugin, and are attempting to use it's LoadScript API call.
(Please don't assume everyone here would guess this, or be bothered to look for it. It's vital information that must form part of your questions)
The script you're writing attempts to set Backup - but your script, as written - does not separate lines with newline characters. As the first line is a comment, the entire script will be ignored.
Basicallty the script you've written looks like this, which is all treated as a comment.
--[[ comment ]]--Backup="Hello!"
You need to write a "\n" after the comment (and, I'd recommend in other places too) to make it like this. In fact, you don't really need block comments at all.
-- comment
Backup="Hello!"
I have a Windows executable (whoami) which is crashing every so often. It's called from another process to get details about the current user and domain. I'd like to know what parameters are passed when it fails.
Does anyone know of an appropriate way to wrap the process and write it's command line arguments to log while still calling the process?
Say the command is used like this:
'whoami.exe /all'
I'd like a script to exist instead of the whoami.exe (with the same filename) which will write this invocation to log and then pass on the call to the actual process.
From a batch file:
echo Parameters: %* >> logfile.txt
whoami.exe %*
With the caveat that you can have problems if the parameters contain spaces (and you passed the in escaping with "), because the command-line parser basically de-escapes them and they should be re-escaped before passed to an other executable.
You didn't note which programming language. It is not doable from a .bat file if that's what you wanted, but you can do it in any programming language. Example in C:
int main(int argc, void **argv)
{
// dump contents of argv to some log file
int i=0;
for (i=0; i<argc; i++)
printf("Argument #%d: %s\n", argv[i]);
// run the 'real' program, giving it the rest of argv vector (1+)
// for example spawn, exec or system() functions can do it
return 0; // or you can do a blocking call, and pick the return value from the program
}
I don't think using a "script" will work, since the intermediate should have a .exe extension for your ploy to work.
I would write a very small command line program to do this; something like the following (written in Delphi/Virtual Pascal so it will result in a Win32 executable, but any compiled language should do):
program PassThrough;
uses
Dos; // Imports the Exec routine
const
PassTo = 'Original.exe'; // The program you really want to call
var
CommandLine: String;
i: Integer;
f: Text;
begin
CommandLine := '';
for i := 1 to ParamCount do
CommandLine := CommandLine + ParamStr(i) + ' ';
Assign(f,'Passthrough.log');
Append(f);
Writeln(f, CommandLine); // Write a line in the log
Close(f);
Exec(PassTo, CommandLine); // Run the intended program
end.
Can't you just change the calling program to log the parameters it used to call the process, and the exit code?
This would be way easier than trying to dig into whoami.exe
Look for whoami.exe, BACK IT UP, replace it with your own executable and see do whatever you like with it's parameters (maybe save them in a text file).
If you can reproduce the crash, use Process Explorer before crashed process is terminated to see its command line.
http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx
This is related to: How do I read the results of a system() call in C++?
I am trying to do the exact the same thing only that my program needs to pass 'multiple parameters with spaces' to the command. I need the command line output and the exit code from the process.
Example: An example with Textpad. The application I'm really using prints stuff on stdout.
string command1 = "\"C:\Program Files\TextPad 5\Textpad.exe\" C:\readme0.txt";
string command2 = "\"C:\Program Files\TextPad 5\Textpad.exe\" \"C:\read me2.txt\"";
cout << system(command1.c_str()) << endl;
cout << system(command1.c_str()) << endl;
Output:
0
'C:\Program' is not recognized as an internal or external command,
operable program or batch file.
1
The first call to system passes and second one fails with the error above. _popen in Windows works similarly on Windows so no help there. I can easily do this on Linux as I can escape spaces in the parameters without having to use quotes.
An alternative is to write a huge chunk of non-cross-platform code as listed here:
http://msdn.microsoft.com/en-us/library/ms682499(VS.85).aspx
But in case I want to avoid that, are there any alternatives to system() and _popen() on Windows?
Thanks!
The lowest level Windows API function used by _popen() and system() is CreateProcess().
However CreateProcess() is not that simple to use - especially when you want to get the process'es output or write to the process'es input.
CreateProcess() will definitely work with file names that contain space characters (as long as they are written in quotation marks the way you did that).
The following solves the spaces in the path problem. Catching the output of the command is much more difficult, however:
#include <string>
#include <cstdlib>
using namespace std;
int main() {
string cmd = "\"c:\\program files\\notepad++\\notepad++.exe\"";
system( cmd.c_str() );
return 0;
}
A bunch of utility libraries have taken that chunk of non-portable code and wrapped it up with a portable interface. For an example, see Qt's QProcess.
I do this (note - this is VB.NET code), so I can write the output of the command to my log file (it's wrapped in a RunCommand() method):
Try
Dim myprocess As New Process()
myprocess.StartInfo.FileName = "C:\Program Files\TextPad 5\Textpad.exe"
myprocess.StartInfo.RedirectStandardOutput = True
myprocess.StartInfo.UseShellExecute = False
' inArgs are the arguments on the command line to the program
myprocess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden
myprocess.StartInfo.Arguments = "C:\readme0.txt"
' the dir to set as default when the program runs
Then myprocess.StartInfo.WorkingDirectory = "C:\Program Files\TextPad 5\"
myprocess.Start()
' grab a reader to the standard output of the program
procReader = myprocess.StandardOutput()
' read all the output from the process
While (Not procReader.EndOfStream)
procLine = procReader.ReadLine()
' write the output to my log
writeNotes(procLine)
End While
procReader.Close()
Catch ex As Exception
' Write the error to my log
writeErrors("Couldn't execute command "C:\Program Files\TextPad 5\Textpad.exe", ex)
End Try
I think ShellExecute() is what you're looking for.
Never use system() in Windows !
Just redirect i/o handles.