Solved

Parenthesis in Switch passed to a Dos Program causes program to fail

Posted on 2013-01-07
17
309 Views
Last Modified: 2013-01-08
I have a dos script that one of the switches (P5) may or may not include parenthesis .   When it does, this section of code fails, when it doesn't this code works fine.

Can someone show how I can allow ( ) to be included in the P5 switch without causing the code to fail.  

For the background on this code, see 7951888.html.

This programs purpose is to intercept  the parms that are passed from program A to program B.  It works great except for these rare instances.

*************************************
Here is the command line switches that are passed:  Note the (Monthly)_dog) .
*************************************

Show Parms 0-9 before processing      
------------------------            
**Parms 0-9 Command Line**       
1sys010464886158.txt -tf 1sys010464886158-to.txt -s Report#64869709(Customer_Ranking_by_MARGIN_(Monthly)_dog) -attach
E:\NxT\rd\tmp\mail7404.pdf      
-----------------------

Here they are broken down

P0=e:\blat\blatcapture.cmd                  
p1=1sys010464886158.txt                  
p2=-tf                  
p3=1sys010464886158-to.txt                  
p4=-s                  
p5=Report#64869709(Customer_Ranking_by_MARGIN_(Monthly)_dog)                  
p6=-attach                  
p7=E:\NxT\rd\tmp\mail7404.pdf                  
p8=                  
p9=                  

*****************************************
Here is the extract code:
*****************************************

REM Init index for non switch parms
set Index=0

REM ------------------------
REM Loop until no more parms found
REM ------------------------
:DoParms
  if "%~1" EQU "" goto :GotParms

  REM Get this parm into a variable
  set Parm=%1
  REM Is it a switch (starts with a -)
  if "!Parm:~0,1!" EQU "-" (
    REM If switch, then save the next parm in a Switch- variable
    set Switch!Parm!=%2
    shift
  ) else (
    REM Not a switch, save in next Parm- variable
    set /A Index+=1
    set Parm-!Index!=%1
  )
  shift
  goto :DoParms


Thanks for any help you might can provide.
0
Comment
Question by:HCSHAW
  • 9
  • 3
  • 3
  • +1
17 Comments
 
LVL 17

Expert Comment

by:Kent Dyer
ID: 38752430
How about passing CHAR(40) and then CHAR(41) for your right/left parens respectively in either VBSCript or in KIXtart?

HTH,

Kent
0
 

Author Comment

by:HCSHAW
ID: 38752451
Thanks Kent, but the calling program does not allow me to modify the switches.  If the data it is working with has the ( ) then that is what is being passed along.   If it is any help, when that program builds p5 it is seeing the following.

Report#64869709
Customer_Ranking_by_MARGIN_(Monthly)_dog

It concatenates it to
Report#64869709(Customer_Ranking_by_MARGIN_(Monthly)_dog)  
so it is adding in an extra set of ( ).
0
 
LVL 17

Expert Comment

by:Kent Dyer
ID: 38752496
Maybe I am not being too clear..

This should do what you need..
Cmd = "1sys010464886158.txt -tf 1sys010464886158-to.txt -s Report#64869709" & Char(40) & "Customer_Ranking_by_MARGIN_" & Char(40) & "Monthly" & Char(41) & "_dog" & chr(41) & " -attach E:\NxT\rd\tmp\mail7404.pdf"

Open in new window


HTH,

Kent
0
 
LVL 9

Expert Comment

by:Beartlaoi
ID: 38752497
The way I solved this kind of problem was I wrote a little exe that does nothing more than pass its parameters to the cmd but placing quotes around the parameters based on their contents.
I configured the program to use this exe instead of the .cmd
If you have a C++ compiler I can give you my existing code.  Otherwise I could try to convert it to .Net for you.
0
 

Author Comment

by:HCSHAW
ID: 38752586
Kent, I see what you are saying, but I am limited in that I cannot modify program A or its output.

 Beartlaoi,  You have triggered a thought.   Maybe what I really need to do is add a piece of code to strip the ( ) out of parm 5 BEFORE running it through the routine.   I could substitute them with underscores.   Do you have an easy way to do this using dos?
0
 
LVL 1

Expert Comment

by:bmarone
ID: 38752593
REM Using Intermediate variables to build Parm/Switch names

REM Init index for non switch parms
set Index=0

REM ------------------------
REM Loop until no more parms found
REM ------------------------
:DoParms
  if "%~1" EQU "" goto :GotParms

  set /A Index+=1
  set ParmName=Parm%Index%
  set SwitchName=Switch%Index%
  set ParmTemp=%1
  set %ParmName%=%ParmTemp%
  echo ParmTemp=%ParmTemp%
  shift
  set SwitchTemp=%1
  if "%ParmTemp:~0,1%" EQU "-" set %SwitchName%=%SwitchTemp%
  if "%ParmTemp:~0,1%" EQU "-" echo SwitchTemp=%SwitchTemp%
  if "%ParmTemp:~0,1%" EQU "-" shift

  goto DoParms

:GotParms
REM Display variables
echo Parm1=%Parm1%
echo Switch1=%Switch1%
echo Parm2=%Parm2%
echo Switch2=%Switch2%
echo Parm3=%Parm4%
echo Switch3=%Switch3%
echo Parm4=%Parm4%
echo Switch4=%Switch4%
0
 
LVL 9

Expert Comment

by:Beartlaoi
ID: 38752621
Try this:
set Test=(Customer_Ranking_by_MARGIN_(Monthly)_dog)
set Test=%Test:(=_%
set Test=%Test:)=_%

This is based on StackOverflow - how to replace string inside a bat file with command line parameter string
0
 

Author Comment

by:HCSHAW
ID: 38752644
bmarone,
Thanks for the code example.  In looking over it it appears to change the variable names to NAME1, NAME2, etc.   The way the program currently works is it creates a variable name using the -  (dash) value.  

For Instance take the  -tf 1sys010464886158-to.txt.  

The program creates the following   [Variable name Switch-tf  and the value is 1sys010465368900-to.txt]
Switch-tf=1sys010465368900-to.txt

Your example code could possibly be modified to accommodate this, but I was hoping to avoid rewriting the code.
0
Highfive Gives IT Their Time Back

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 1

Expert Comment

by:bmarone
ID: 38752694
Just following suit.  Then it sounds like probably not a need for the Index variable. Did you mean you don't want to rewrite the CMD file code, or changing the CMD file is OK, just not change PROGRAM1.EXE and PROGRAM2.EXE.  Are you looking for this output:
  Switch-tf=1sys010464886158-to.txt
  Switch-s=Report#64869709(Customer_Ranking_by_MARGIN_(Monthly)_dog)
  Switch-attach=E:\NxT\rd\tmp\mail7404.pdf    
... and do you need a variable set for the first parameter (1sys010464886158.txt)?

Edit:
::: Revised Code
Set AllParms=%*

REM Loop until no more parms found
:DoParms
  if "%~1" EQU "" goto :GotParms
  set ParmTemp=%1
  if "%ParmTemp:~0,1%" EQU "-" goto ItsASwitch
  shift
  goto DoParms

:ItsASwitch
  set SwitchName=Switch%1
  shift
  set %SwitchName%=%1
  shift
  goto DoParms

:GotParms
echo Switch-tf=%Switch-tf%
echo Switch-s=%Switch-s%
echo Switch-attach=%Switch-attach%

call Program2.exe %AllParms%
0
 

Author Comment

by:HCSHAW
ID: 38752773
bmarone
You are correct. here is how they need to end up.

Local Variables that were set  
                         
Switch-attach=E:\NxT\rd\tmp\mail7407.pdf
Switch-s=Report#65357416(Customer_Ranking_by_MARGIN_Monthly
Switch-tf=1sys010465368900-to.txt
Parm-1=1sys010465368900.txt
Parm-2=Report#65357416(Customer_Ranking_by_MARGIN_Monthly)

I am experimenting with  Beartlaoi solution to strip the ( ) out of P5.  It looks like this might work for this solution.  

Beartlaoi,
Your code has been translated as follows for this program.   I just want to reassign %5 to the value that is created in TEMPP5.   Forgive me for being lame, but the life of me, I can't get the %5 to get assigned.   I know it is some simple syntax.  Can you see what the issue is .  As you might notice, I don't do this often enough to know all the gotchas of Dos.

Rem Clean up P5 of any ( )
set TempP5=%5
set TEMPP5=%TEMPP5:(=_%
set TEMPP5=%TEMPP5:)=_%
set %5=%TEMPP5%
0
 

Author Comment

by:HCSHAW
ID: 38752796
bmarone
From your approach, it looks like you are trying to eliminate the issue with the  ( ) by changing the IF around.  Do you feel that he ( )  in P5 are getting interpreted as part of the command string by the parser?  Just a curiosity question.
0
 
LVL 9

Assisted Solution

by:Beartlaoi
Beartlaoi earned 250 total points
ID: 38752824
You cant re-assign %5 since it is a passed-in parameter.
If you have First.cmd that calls the calling program that then calls blatcapture.cmd then the First.cmd should just pass %TEMPP5% instead of %5 to the program.
0
 

Author Comment

by:HCSHAW
ID: 38752834
That's what I was suspecting.   I was just hoping there was a little magic trick to make it work.  I will give that a try.
0
 
LVL 1

Accepted Solution

by:
bmarone earned 250 total points
ID: 38752839
Yes, it seems so.  If you could pass quotes around the parm it could work, but of course Program2 may not like the quotes.

In your last question, you can't reset the %5 variable, as it is not a variable per se, but a value set by the command shell indicative of what it received/parsed.  If you wanted to pass the _modified_ version of %5, you could change the batch to parse & concatenate, eliminating the "()" in %5 before you concat that parameter back.

set AllParms=%*
:DoParms
  if "%~1" EQU "" goto GotParms
  set ParmTemp=%1
  set ParmTemp=%ParmTemp:(=_%
  set ParmTemp=%ParmTemp:)=_%
  set NewParms=%NewParms% %ParmTemp%
  shift
  goto DoParms

:GotParms
call Program2.exe %NewParms%
0
 

Author Comment

by:HCSHAW
ID: 38752891
Okay guys, both of these are excellent points.  Thanks for commenting.   My deli-ma is that the code I was trying not to modify is taking the command parms %1..%9 in order.

That means that if I use the clean up technique before the loop, the loop will still be processing %5 not the cleaned up %tempp5%.    Ahggggg.   This leans me toward what it seems both of you have concluded.   I will need to interject a program to strip the ( ) in the  incoming parms, and then pass along to blatcapture.
 
bmarone, your code example seems to be a straightforward example of how to code for this cleanup program.  thx.

 Thank you all for your prompt and informative responses.
0
 

Author Closing Comment

by:HCSHAW
ID: 38752903
Thanks again for the hearty dialogue.
0
 

Author Comment

by:HCSHAW
ID: 38757182
Just a recap for those who came here to find an answer to your ( ) problem.

First ( ) in a Parm that was processed by the IF ELSE was causing the code to fail.  For some reason it was recognizing the ( ) in the Parm as part of the code and was aborting the routine.  I coded a stripper (see bmarone's comments above) to remove the ( ) and this worked but wasn't a clear coding solution.  I also wanted to leave the ( ) in the Parm if possible since stripping them out made the text less readable.


Second, If statements in DOS are a BEAR.  To do a proper  IF  ELSE that includes more than 1 command you have to use  ( ) in a precise format.
IF test do (
truelogic
) else (
falselogic
)
If you are going to use the ELSE it must be )spaceELSEspace(.   Now there is a lot of dialogue about using the ELSE which you will find when you do your research.   It can be tricky to get the desired result.  My recommendation is to not use the ELSE and write your code with GOTO's. (bmarone's suggested that approach as well).  That said, that is what I ended up doing to clean up the issues I was having.  This code will now accept a parm with ( ) without failing.

Here is how the code was re-written
REM Init index for non switch parms
set Index=0

REM ------------------------
REM Loop until no more parms found
REM ------------------------

:DoParms

echo p1= %1 p2=%2
if "%~1" EQU "" goto :GotParms

REM ----------------
REM Process this Parm
REM ----------------

set Parm=%1
REM set PARM=%PARM:(=_%                       Rem Code let in case need to remove ( )
REM set PARM=%PARM:)=_%      

REM ----------------
REM Is it a switch starts with a -
REM ----------------
 
if "!Parm:~0,1!" NEQ "-" goto :Not-

REM ----------------
REM It is a switch, then save the next parm in a Switch- variable
REM ----------------
                 
set Parm2=%2
REM set PARM2=%PARM2:(=_%            Rem Code let in case need to remove ( )
REM set PARM2=%PARM2:)=_%      

set Switch!Parm!=%PARM2%
shift
shift
Goto :DoParms

REM ----------------
REM  Not a switch, save in next Parm- variable
REM ----------------
:Not-
set /A Index+=1
set Parm-!Index!=%1
SHIFT
goto :DoParms


echo ------------------------
echo All parms processed, display them
echo ------------------------
:GotParms
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

This article was inspired by a question here at Experts Exchange (http://www.experts-exchange.com/Software/Photos_Graphics/Images_and_Photos/Q_28629170.html). The requirements stated in that question are (1) reduce the file size of a large number of…
Learn about cloud computing and its benefits for small business owners.
It is a freely distributed piece of software for such tasks as photo retouching, image composition and image authoring. It works on many operating systems, in many languages.
Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…

706 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

19 Experts available now in Live!

Get 1:1 Help Now