Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1118
  • Last Modified:

Capturing / Setting Return Value From a Pearl Script to a DOS Bat file

I execute the following Dos.bat file (readfile.bat) which in turn runs a PerlScript (ReadFile.PL)
ReadFile simply opens a file and copies it to a second file and keeps a recordcount.
My problem is that the %errorlevel% value in the Dos bat file is not the same value which I exit or print to STDERR from the Perl script.

Any ideas?  Can someone please explain if the correct method is to use Exit $nn or do I need to do something else? The file has 120846 records but the %errorlevel% is coming back as 4776.

I'm confused and desperate. Please help !!! Thanks.

BEGIN CODE:ReadFile.Bat
===================
@echo off
perl C:\Data\ReadFile.pl %*
echo %errorlevel%
END BATCH FILE


BEGIN PERL SCRIPT
===============
#readfile.pl
$filenameIN = $ARGV[0];;
$filenameOUT = $ARGV[1];;
open (INFILE, "$filenameIN") || die "Can't open input file: $!";
open(OUTFILE, ">$filenameOUT") || die "Can't open input file: $!";
$nn = 0;

while (<INFILE>){
print OUTFILE;
$nn++;
}

close (INFILE);
close (OUTFILE);
unlink $filenameIN;
print $nn;
exit $nn;

0
MarcRosenberg
Asked:
MarcRosenberg
  • 4
  • 2
3 Solutions
 
gripeCommented:
Your code works unedited here. It's possible that you're overwriting the values you're printing out because you're not terminating your print statements with a newline "\n". Note the following test:

 C:\temp>type ReadFile.bat
@echo off
perl C:\temp\readfile.pl %*
echo %errorlevel%

C:\temp>type readfile.pl
#readfile.pl
$filenameIN = $ARGV[0];;
$filenameOUT = $ARGV[1];;
open (INFILE, "$filenameIN") || die "Can't open input file: $!";
open(OUTFILE, ">$filenameOUT") || die "Can't open input file: $!";
$nn = 0;

while (<INFILE>){
print OUTFILE;
$nn++;
}

close (INFILE);
close (OUTFILE);
unlink $filenameIN;
print $nn;
exit $nn;



C:\temp>perl -wle"print qq{$_} for 1..2000"  > test.txt

C:\temp>ReadFile.bat test.txt test2.txt
20002000

C:\temp>

As you can see above, the output from both the 'print $nn;' Perl statement and the 'echo %errorlevel%' are both '2000'. Since the perl print is not terminated with a newline, they appear on the same line.

I would say something else is wrong if you're not seeing similar behaviour.

0
 
gripeCommented:
Ah ha, after writing that I had an epiphany and tried the same test with a file with more records...

It looks like the %errorlevel% variable has a 16 bit (IE: 65535 values) limit to the values it holds and will overflow when given a larger number. Note the following test:

C:\temp>echo %errorlevel%
65535

C:\temp>perl -wle"exit 65536;"

C:\temp>echo %errorlevel%
0

C:\temp>perl -wle"exit 65537;"

C:\temp>echo %errorlevel%
1

C:\temp>

You'll need to think of a different way of returning your value to your calling batch program.
0
 
kanduraCommented:
gripe,
the problem is that passing a value greater than say 16348 through %errorlevel% doesn't work. What we need is a way to capture the return value from the perl script in a variable.
Unfortunately I know nothing of dos or vb :(


0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
kanduraCommented:
for /f %%a in ('perl perl C:\Data\ReadFile.pl %*') DO SET RECORD_COUNT=%%a
echo Record count is %RECORD_COUNT%
0
 
kanduraCommented:
uhm, one "perl" is enough there...
anyway, that catches the output from the script in RECORD_COUNT.
In this example, only the last printed line survives, so you should get the $nn from the print statement.
0
 
MarcRosenbergAuthor Commented:
gripe and kandura:

I would like to thank you both for solving this problem. I never would have suspected this issue with %ErrorLevel% being limited to 16 bit values. I have implemented kandura's batch commands and am sucessfully retrieving the %Record_Count% variable back to Readfile.bat.

If I may ask for one last piece of assistance and one question....

I am still not able to get the handle to the %Record_Count% variable back to my VB code.

I am exiting Readfile.bat with
exit /b %RECORD_COUNT%

The VB code shells out to Readfile.bat using WIN32 API's contained in a function ExecCmd

Public Function ExecCmd(cmdline$)

   ' Start the shelled application:
   lngRetcode = CreateProcessA(vbNullString, cmdline$, 0&, 0&, 1&, _
      &H20&, 0&, vbNullString, start, proc)

   ' Wait for the shelled application to finish:
      lngRetcode = WaitForSingleObject(proc.hProcess, INFINITE)
      Call GetExitCodeProcess(proc.hProcess, lngRetcode)
      Call CloseHandle(proc.hThread)
      Call CloseHandle(proc.hProcess)
      ExecCmd = lngRetcode
End Function


It always returns a zero. Upon doing some research I found that GetExitProcessCode always returns a zero for 16-Bit Processes. Does this explain the problem? Do bat files run in a 16 Bit process? I suspect not because of the declaration below which references kernel32....

Private Declare Function CreateProcessA Lib "kernel32" (ByVal _
      lpApplicationName As String, ByVal lpCommandLine As String, ByVal _
      lpProcessAttributes As Long, ByVal lpThreadAttributes As Long, _
      ByVal bInheritHandles As Long, ByVal dwCreationFlags As Long, _
      ByVal lpEnvironment As Long, ByVal lpCurrentDirectory As String, _
      lpStartupInfo As STARTUPINFO, lpProcessInformation As _
      PROCESS_INFORMATION) As Long


As for my question... could you please explain what the /f  switch is doing in your command:
for /f %%a in ('perl C:\Data\ReadFile.pl %*') DO SET RECORD_COUNT=%%a

Thanks very much for your assistance. I will award you both points for the work you have done so far.


0
 
kanduraCommented:
MarcRosenberg,

> I am still not able to get the handle to the %Record_Count% variable back to my VB code.

The problem is that you're going about it in the wrong way, and I suppose we should have noticed that earlier on. The process exit code is always numerical, and only used to indicate whether the process ended successfully or with an error. 0 means success, and a non-zero should map to a (documented) error condition.
The situation is the same as in perl with system versus backticks: you can not capture the output from a "system" command, you need to use backticks or pipes (a la open my $pipe, " |some_command" ).
We managed to capture process output in a batch file, which is nice, but now you still need to know how to do it in VB. The fact that you're now CreateProcess'ing a bat file instead of a perl file makes no difference.

I did a bit of googling (on <<"Visual Basic" capture command output>>), and found one way that uses pipes (which it connects to the stdout and stdin of the process). You can find the code here: http://www.freevbcode.com/ShowCode.Asp?ID=3957
Note that I neither wrote it nor tested it, so please review carefully.


> As for my question... could you please explain what the /f  switch is
> doing in your command:
> for /f %%a in ('perl C:\Data\ReadFile.pl %*') DO SET RECORD_COUNT=%%a

What it stands for, I don't know. Try "help for" in a dos prompt to see it described in your language (mine is dutch, so I won't paste that here ;^)
0

Featured Post

Hire Technology Freelancers with Gigs

Work with freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely, and get projects done right.

  • 4
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now