• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 335
  • Last Modified:

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

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
HCSHAW
Asked:
HCSHAW
  • 9
  • 3
  • 3
  • +1
2 Solutions
 
Kent DyerCommented:
How about passing CHAR(40) and then CHAR(41) for your right/left parens respectively in either VBSCript or in KIXtart?

HTH,

Kent
0
 
HCSHAWAuthor Commented:
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
 
Kent DyerCommented:
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
Free learning courses: Active Directory Deep Dive

Get a firm grasp on your IT environment when you learn Active Directory best practices with Veeam! Watch all, or choose any amount, of this three-part webinar series to improve your skills. From the basics to virtualization and backup, we got you covered.

 
BeartlaoiCommented:
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
 
HCSHAWAuthor Commented:
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
 
bmaroneCommented:
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
 
BeartlaoiCommented:
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
 
HCSHAWAuthor Commented:
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
 
bmaroneCommented:
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
 
HCSHAWAuthor Commented:
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
 
HCSHAWAuthor Commented:
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
 
BeartlaoiCommented:
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
 
HCSHAWAuthor Commented:
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
 
bmaroneCommented:
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
 
HCSHAWAuthor Commented:
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
 
HCSHAWAuthor Commented:
Thanks again for the hearty dialogue.
0
 
HCSHAWAuthor Commented:
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

Free learning courses: Active Directory Deep Dive

Get a firm grasp on your IT environment when you learn Active Directory best practices with Veeam! Watch all, or choose any amount, of this three-part webinar series to improve your skills. From the basics to virtualization and backup, we got you covered.

  • 9
  • 3
  • 3
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now