Solved

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

Posted on 2004-10-01
7
1,057 Views
Last Modified: 2008-01-09
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
Comment
Question by:MarcRosenberg
  • 4
  • 2
7 Comments
 
LVL 13

Expert Comment

by:gripe
ID: 12205017
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
 
LVL 13

Assisted Solution

by:gripe
gripe earned 200 total points
ID: 12205078
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
 
LVL 18

Expert Comment

by:kandura
ID: 12205094
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
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 18

Accepted Solution

by:
kandura earned 300 total points
ID: 12205144
for /f %%a in ('perl perl C:\Data\ReadFile.pl %*') DO SET RECORD_COUNT=%%a
echo Record count is %RECORD_COUNT%
0
 
LVL 18

Expert Comment

by:kandura
ID: 12205311
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
 
LVL 2

Author Comment

by:MarcRosenberg
ID: 12218411
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
 
LVL 18

Assisted Solution

by:kandura
kandura earned 300 total points
ID: 12219324
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

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

On Microsoft Windows, if  when you click or type the name of a .pl file, you get an error "is not recognized as an internal or external command, operable program or batch file", then this means you do not have the .pl file extension associated with …
A year or so back I was asked to have a play with MongoDB; within half an hour I had downloaded (http://www.mongodb.org/downloads),  installed and started the daemon, and had a console window open. After an hour or two of playing at the command …
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…
Here's a very brief overview of the methods PRTG Network Monitor (https://www.paessler.com/prtg) offers for monitoring bandwidth, to help you decide which methods you´d like to investigate in more detail.  The methods are covered in more detail in o…

746 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now