Break apart the command line like a batch file.

Technical support and scripting issues

Moderators: Dorian (MJT support), JRL

Post Reply
chihuahualand
Junior Coder
Posts: 35
Joined: Thu Jan 12, 2006 9:20 pm
Contact:

Break apart the command line like a batch file.

Post by chihuahualand » Tue Mar 24, 2009 12:43 pm

This is similar to the issues of a one-line CSV file, but now SPACE is a delimiter (I tested... commas separate fields for batch files too).

Any body have any good ideas for this?

I suppose the easiest if to create a batch file on the fly and pass the command line, then collect the answers.

The goal is to replicate this:

C:\type test.bat
@echo off
echo 1= %1
echo 2= %2
echo 3= %3
echo 4= %4
echo 5= %5

C:\test "this is a test" "x" , "5" "6",7
1= "this is a test"
2= "x"
3= "5"
4= "6"
5= 7

User avatar
JRL
Automation Wizard
Posts: 3526
Joined: Mon Jan 10, 2005 6:22 pm
Location: Iowa

Post by JRL » Tue Mar 24, 2009 1:21 pm

Can you do a stringreplace> on the commas replacing them with spaces, then separate the command line by %space%?

User avatar
Marcus Tettmar
Site Admin
Posts: 7395
Joined: Thu Sep 19, 2002 3:00 pm
Location: Dorset, UK
Contact:

Post by Marcus Tettmar » Tue Mar 24, 2009 1:33 pm

Compile the following as a console app:

Code: Select all

// COMPILE_OPTS|C:\Documents\test.exe||CONSOLE=1|INCLUDES=1| /NOSYSTRAY /HIDE /LOGFILE=\dev\nul
Let>text=COMMAND_LINE

//RegEx to extract each field to an array
Let>pattern="[^"\r\n]*"
RegEx>pattern,text,0,fields,num,0

Let>k=0
Repeat>k
  Let>k=k+1
  Let>this_field=fields_%k%
  SOWriteLn>%k%=%this_field%%CRLF%
Until>k=num
As long as each parm is in quotes it will do as you want. E.g.:

test.exe "this is a test" "x" "5" "6" "7"

Commas between fields are optional. Just as long as each field is in quotes.
Marcus Tettmar
http://mjtnet.com/blog/ | http://twitter.com/marcustettmar

Did you know we are now offering affordable monthly subscriptions for Macro Scheduler Standard?

chihuahualand
Junior Coder
Posts: 35
Joined: Thu Jan 12, 2006 9:20 pm
Contact:

Post by chihuahualand » Tue Mar 24, 2009 11:45 pm

StringReplace, Separate, et al. don't work except under very simple cases.

The problem with the RegEx solution is, once again, expecting well-formed data. Numerics, for instance, are "generally" not wrapped in quotes

Just like trying to do CSV by hand (not using MS text driver, Excel, etc.), the simple case goes to the very complicated. Handling each byte one by one... looking for quoted data... double quotes that need consideration and conversion... extra spaces... it's a programing mess. It can be done obviously, but, it's always a clunky chunk of code that tends to dwarf the actual mission... or so says I.

Anyways, Anybody know why the following sets up the environment variable, but it's not available using GetEnvVar?

The thought process: to create a batch file on-the-fly, pass the commandline, have the batch file pass the delimited data back to the script by way of the designated ENV variable. I suppose I could use a file, but, jeez, that's a lot of temp files. Perhaps that's easier than messing with the environment variable stuff... seemed like a cute trick.
VBstart
Function CreateENV1(Zname, Zvalue)
' this method didn't seem to work...
strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set objVariable = objWMIService.Get("Win32_Environment").SpawnInstance_
objVariable.Name = Zname
objVariable.UserName = "System"
objVariable.VariableValue = Zvalue
objVariable.Put_
CreateENV1 = "done"
End Function

Function CreateENV2(Zname, Zvalue)
' the results can be viewed using SET in a command window
SET oShell = CREATEOBJECT("Wscript.Shell")
SET wSystemEnv = oShell.Environment("SYSTEM")
wSystemEnv(Zname) = Zvalue
SET wSystemEnv = NOTHING
SET oShell = NOTHING
CreateENV2 = "done"
End Function

VBend

MDL>%command_line%
Position>",%command_line%,2,location,False
Add>location,1
Midstr>%command_line%,%location%,10000,res
MDL>res

VBEval>CreateENV2("TESTNAME1","TestValue"),result
MDL>result

Let>EnvName=TESTNAME1
GetEnvVar>%EnvName%,env
MDL>env

User avatar
JRL
Automation Wizard
Posts: 3526
Joined: Mon Jan 10, 2005 6:22 pm
Location: Iowa

Post by JRL » Wed Mar 25, 2009 3:49 am

Anyways, Anybody know why the following sets up the environment variable, but it's not available using GetEnvVar?
Its just speculation on my part as to why it doesn't work, but I've tried the same in the past using DOS and it doesn't work. I think possibly it has to do with the environment variable being owned by a particular thread.

The following illustrates the same. Run the following. The DOS window will stay open. Type "set" in the DOS window and press return and you will see that the environment variable "username" has been reset to "123456". However, the Macro Scheduler message will display the original value of the variable.

Code: Select all

Run>cmd /k set username=123456
GetEnvVar>username,var
mdl>var
Just like trying to do CSV by hand... ...it's always a clunky chunk of code that tends to dwarf the actual mission... or so says I.
I agree.
Since you know that the batch file will handle all of your expected circumstances, I think you're just as well off writing to a temporary file. Personally, I like using temporary files. I've used them extensively and have many samples on the forum using temporary files.

Not to complicate things but you could write the batch file and use Clip.exe to put the results to the clipboard. Then retrieve them using the GetClipBoard> function.

User avatar
Marcus Tettmar
Site Admin
Posts: 7395
Joined: Thu Sep 19, 2002 3:00 pm
Location: Dorset, UK
Contact:

Post by Marcus Tettmar » Wed Mar 25, 2009 10:47 am

I know I've tried to explain this before, and somewhere there's a post pointing to microsoft's documentation about environment variables. The point is they are process specific. A windows app can't read the enviroment variables set by another app or by a command console and vice versa.

However, if you compile your script to a CONSOLE app then run it FROM THE CONSOLE it WILL be able to see any environment variables set in that console, because the process is then owned by the console. If you compile as a regular windows app it will NOT be able to see them.

E.g. compile the following script to a CONSOLE app called testenv.exe:

GetEnvVar>fred,v
SOWriteLn>v

Now from a CMD prompt do:

Set fred=foo

Then FROM THE CMD prompt run the console app you just created

c:\>testenv.exe
foo

It will output the value of the environment variable. If you compile it to a regular windows (non console) app you will see nothing output, because it does not know about the console processes environment variables.
Marcus Tettmar
http://mjtnet.com/blog/ | http://twitter.com/marcustettmar

Did you know we are now offering affordable monthly subscriptions for Macro Scheduler Standard?

chihuahualand
Junior Coder
Posts: 35
Joined: Thu Jan 12, 2006 9:20 pm
Contact:

Post by chihuahualand » Wed Mar 25, 2009 9:15 pm

My Solution:

Code: Select all

Let>space={" "}
Concat>command_line,%space%
Position>%space%,%command_line%,2,found,False
MidStr>%command_line%,1,1,result
If>result<noQuote>",%command_line%,2,found,False
Label>noQuote
Add>found,1
Midstr>%command_line%,%found%,10000,args
Let>arg_count=1
StringReplace>args,%space%,,result
If>result=,exit
Let>batfile=%temp_dir%.\~tmp.bat
Let>tmpfile=%temp_dir%.\~tmp.txt
DeleteFile>%batfile%
DeleteFile>%tmpfile%
WriteLn>%batfile%,result,@echo off
Let>WLN_NOCRLF=1
WriteLn>%batfile%,result,if ~%1~==~~
Let>WLN_NOCRLF=0
WriteLn>%batfile%,result, %batfile% %args%
WriteLn>%batfile%,result,shift
WriteLn>%batfile%,result,:loop
Let>WLN_NOCRLF=1
WriteLn>%batfile%,result,echo %0 >>
Let>WLN_NOCRLF=0
WriteLn>%batfile%,result,%tmpfile%
WriteLn>%batfile%,result,shift
WriteLn>%batfile%,result,if not ~%0~==~~ goto :loop
Let>RP_WAIT=1
Run Program>%batfile%
ReadFile>%tmpfile%,result
Separate>result,%CRLF%,arg

Label>Display Results
Sub>arg_count,1
if>arg_count=0,exit
Let>result=
Let>k=0
Repeat>k
Let>k=k+1
Let>thisarg=arg_%k%
ConCat>result,%k%=%thisarg%%crlf%
Until>k,arg_count
MDL>Parameters%crlf%%result%

Label>exit

chihuahualand
Junior Coder
Posts: 35
Joined: Thu Jan 12, 2006 9:20 pm
Contact:

Post by chihuahualand » Wed Mar 25, 2009 10:42 pm

as a macro:

Code: Select all

//BatchParams
//This macro extracts command line parameters like a batch file.
//Returns results joined by CRLF use "Separate>MACRO_RESULT,%CRLF%,arg"
//Invoke: Macro>BatchParams /command_line=%command_line%
Let>space={" "}
Concat>command_line,%space%
Position>%space%,%command_line%,2,found,False
MidStr>%command_line%,1,1,result
If>result<>",noQuote
Position>",%command_line%,2,found,False
Label>noQuote
Add>found,1
Midstr>%command_line%,%found%,10000,args
Let>arg_count=0
StringReplace>args,%space%,,result
Let>MACRO_RESULT=
If>result=,exit
Let>batfile=%temp_dir%.\~tmp.bat
Let>tmpfile=%temp_dir%.\~tmp.txt
DeleteFile>%batfile%
DeleteFile>%tmpfile%
WriteLn>%batfile%,result,@echo off
Let>WLN_NOCRLF=1
WriteLn>%batfile%,result,if ~%1~==~~
Let>WLN_NOCRLF=0
WriteLn>%batfile%,result, %batfile% %args%
WriteLn>%batfile%,result,shift
WriteLn>%batfile%,result,:loop
Let>WLN_NOCRLF=1
WriteLn>%batfile%,result,echo %0 >>
Let>WLN_NOCRLF=0
WriteLn>%batfile%,result,%tmpfile%
WriteLn>%batfile%,result,shift
WriteLn>%batfile%,result,if not ~%0~==~~ goto :loop
Let>RP_WAIT=1
Run Program>%batfile%
ReadFile>%tmpfile%,args
Length>args,result
Sub>result,2
MidStr>args,1,result,MACRO_RESULT
Label>exit


Post Reply
Sign up to our newsletter for free automation tips, tricks & discounts