Monday, December 15, 2008

Automating DOS Command Shell (batch file) multiple Inputs

Another wonderful problem I had been working was automate the command line input of a batch file. I have used redirect and pipe in both <x>nix and Windows platforms but had to spend more hours in troubleshooting this particular issue as there was no generally knows answers.

I've a batch file which takes couple of input by prompting at the shell. The content of the batch file named 'askquestion.bat' is given below:

@echo off
:step1
set A1=
set A2=
set /a COUNT=1

:step2
set /p A1=What is your name?
echo Hi %A1%,

:step3
set /p A2=How old are you?
if "%A2%"=="" set A2=0
set /a A2=1+("%A2%")-1 > nul 2>&1
if not ERRORLEVEL 0 set A2=0
if /i "%1"=="noval" goto :step4

if %A2% LEQ 0 (
echo %A1%, '%A2%' may not be a valid age, please try again.
set /a COUNT+=1
if %COUNT% GEQ 5 goto :step4
goto :step3
)

:step4
if %A2% LEQ 10 echo Welcome kid
echo Name:%A1%, Age:%A2%
echo bye
set A1=
set A2=
set COUNT=

It prompts for two inputs - name and age. But the age could be validated and prompted more than once if required. For avoiding infinite loop, the validation will be done for 5 wrong retries.

The common attempt to automate the input would be though using pipe. For single input, we can use echo
c:\>echo Thilak | askquestion.bat
This does not give input for second question and so the script runs on the unfinished (not sure what state it will be) pipe without input causing the script to run 5 retries (or infinitely without that retries check).

How to give multiple input?
Attempt 1:
c:\>echo Thilak\n35 | askquestion.bat
Attempt 2:
c:\>for %a in (Thilak 35) do echo %a | askquestion.bat
Attempt 3:
Create a file with answers in each line and save with a name answer.txt
c:\>type answer.txt | askquestion.bat
Attempt 4:
c:\>echo Thilak & echo 32 | askquestion.bat
Attemp 5:
c:\>(echo Thilak & echo 32) | askquestion.bat

Most of the common approaches failed. This mean to me that there it is a challenge for me. I took it up and started working on it. Google-ing and forum postings did not give answer to the specific scenario.

Dragged further by the attempt 3, I used dir instead of type. Luckily there were lots of files in that folder and my first observation itself gave me a clue.
c:\>dir | askquestion.bat

The important observation is that, the script received it's second input. And the input was taken after 1023 characters. So, this number is a well know one and I was able to do few assumptions quickly that the DOS shell input buffer is of size 1024 and the last character has to be NULL '\0' and so, 1023 character can be taken as input and flushed to receive the next set of inputs.

Now I started changing my answer.txt to have each answer to be of 1023 characters in each line. Line should be terminated with \n (\r\f or [cr][lf]). Basically I used spaces as the filler and it reflected immediately as a wrong choice. I should have used '\0' (NULL) as the fillers, but how? Then I tried another approach - First line with the actual data followed with dummy lines to fill the rest of the 1023 bytes and then the next actual data. During this, I realized that the last answer does not require to follow with the filler.

This was hard to get automated and did not spend much time in using the shell commands. I used to do Perl scripting and thought of using it here. The file name is 'ansquestion.pl'.

my @ans=("Thilak", "10");
open(QUESTION, "|cmd.exe /c askquestion.bat") or die "psht! problem while open.\n";
foreach(@ans){
$|=1;
print QUESTION pack("a1023", ($_, "\n"));
}
close(QUESTION) or die "problem while close";

The Perl pack() method was very handy to solve the filler issue. In the above code, the pack method creates a character byte stream of length 1023 filled with the list of arguments and remaining bytes with NULL. Following command would fulfill my requirement.

c:\>ansquestion.pl | askquestion.bat

Hopefully, someone can find a batch file to generate this output using for, if and echo commands.

Friday, March 07, 2008

My Mobile Story

In today's world, people are more vulnerable to new technologies so easily. I mean it as I could see a drastic adoption of Mobile phone over the land line phone. It all started with only one convenience - be reachable on move. And now, that has come to a stage where the rest of the technology needs to live in this piece of solution.
When I was out of my college, I saw mobile phone which were bulky like walkie-talkie. I heard from the owners that the call rates were arbitrarily high that they use it to get and give the famous 'missed call'. It was used much like a Pager. I was not excited by this.
The time was changing and 'incoming calls' were announced as free of cost. By that time, I got engaged. And badly felt the need for a way to have calls in privacy. Went to a shop in Bangalore with one of my friend and bought a then slim & flip model mobile phone - Ericsson T28s along with connection from SPICE network. I did not have enough information like today to search for the best mobile. This model did attracted me at the first sight. I used it to the most but for voice calls, SMS and address book only. It worked well for 2 years of use until my kid spoiled it with water. The body of the phone was so sturdy that even after multiple drops it did not have any scratch or broken edge.
It was time to get a new phone, now the reason has become that just to be reachable. I went for another best of class mobile - Nokia 3315. I believe this model to be a best as the casing and features were just what I needed. You may be surprised, I used this phone for more than 6 years and that too without changing the original battery. When I 'packed' it, the battery was keeping my phone alive for 3 full days max or 60 min of talk time.
Recently I went for a new mobile, but this time my requirements were different. Professional and personal needs. I did many analysis with many from old to latest 'available' models. Four were my final choices - Moto Rokr E6, Sony Ericsson P1, HTC Touch and Nokia E50. Finally Nokia E50 won the race due to it's compact form, price, business features and software availability. I'm still a satisfied customer of SPICE network and hence did not change it yet.

Monday, February 25, 2008

Java and Perl

When launching an executable created using Perl archive mechanism or kick starting the Perl interpreter from within Java, one might get into an issue of improper i/o handling in their Perl modules. I've not come across a solution so far. The temporary workaround tried is to launch the Perl application in a command shell like
cmd /start /wait <path to perl.exe> <arguments>

Java and Plugin for Win Runner

There was an interesting issue identified, that Win Runner with 1.5 Java Plugin is able to sense 1st window but not the second. It works well if the tool is executed for second time.
Win Runner was launching the Java application and tries to sense a window and its controls. The Java application was using 1.5 private JRE. Private JRE is nothing but bundling a separate copy of JRE along with an application. Public JRE is the one (but mostly many versions of it) available in C:\Program Files\Java\ folder.

Java 1.5 and later versions come with a feature for quick startup. This feature does have a penalty at the first run while creating a jsa file required for quicker startup in later runs. In the context of the issue, the Java application was taking time to show the first window. The Win Runner script used for detecting the window was able to wait and detect it. But there was a time gap for showing second window. In this period Win Runner detection API comes out with -1 (unknown error). After investigation, the first JVM launches another JVM and when there is a point where no JVM is available for Win Runner Java Plugin to work with, it is skipping the process of detecting the Java window by returning -1. There are many valid error return values for the detecting API but -1 is not part of it and code gets skipped in the execution flow.

Adding a validation for -1 and looping the check until some time frame resolved the issue. Looping is important here as Win Runner APIs do have timeout argument. But will not be effective as there is no JVM attached.