Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Command Line Parameters on an EXE
#1
Is it possible to pass these parameters in an exe and roll them into 3 vars?


foobar.exe "c:\foo bar\test.txt" "foobar foo" "bar-foo bar"


var0=c:\foo bar\test.txt
var1=foobar foo
var2=bar-foo bar
An old blog on QM coding and automation.

The Macro Hook
#2
If you run the exe from QM:

Function Function131
Code:
Copy      Help
;/exe
function str'a b

mes _s.format("''%s'', %i" a b)

Macro
Code:
Copy      Help
mac "Function131" "" "x" 5

If not from QM, use tok. Or probably can be used an undocumented command line syntax that QM uses to pass arguments to exe like in the above code.
#3
Example with setstruct/getstruct.

This is better to use when you run the exe from qm but cannot use mac.

Function Function132
Code:
Copy      Help
;/exe
type ZUU str'a b
ZUU z
_s=_command
_s.setstruct(z); err mes- "incorrect command line"
mes _s.format("''%s'', %i" z.a z.b)

Macro
Code:
Copy      Help
type ZUU str'a b
ZUU z
z.a="x"
z.b=8
run "$myqm$\function132" _s.getstruct(z)


----------------

When not from QM.

Function Function133
Code:
Copy      Help
;/exe
type ZU str'Aa b double'c str'd
ZU z
_s=_command
_s.setstruct(z 3); err mes- "incorrect command line"
mes _s.format("''%s'', %f, ''%s''" z.Aa z.c z.d)

Macro
Code:
Copy      Help
str s=
;aa xxx
;c 10.95
;d "line1[]line2"

run "$myqm$\function133" s
#4
This macro statement
mes _command
get me the whole argument passed to the compiled macro.exe file.
I call it using "macro.exe" Hi its me

output

Hi its me, over here.

But if I need need to separate the passed commandline parameter into 2 or 3 or more arguments,
Example
macro.exe "Hi" "its me," "over here."

I need those 2 or 3 arguments for different purposes or when no arguments are passed, can someone show how its done in QM compiled macro.exe? I' m still trying to figure out how QM works(yeah I'm a newbie here:? ). Thanks
#5
Function ParseCommandLine
Code:
Copy      Help
;/
function $cmdLine ARRAY(str)&a

;Parses command line.
;Uses the same rules as most programs. <link "http://www.google.com/search?q=site%3amicrosoft.com%20Parsing%20C%2b%2b%20Command-Line%20Arguments">Read more</link>.

;cmdLine - command line.
;;;Can be path followed by command line. Then a[0] will be the path.
;a - receives command line arguments.


a=0
if(empty(cmdLine)) ret
int i n
word** w=CommandLineToArgvW(@cmdLine &n)
for(i 0 n) a[].ansi(w[i])

LocalFree w

example
Macro Macro1465
Code:
Copy      Help
out

str cl="/A /B bbb /c ''ccc ccc'' ''\''ddd ddd\''''"
;str cl="''c:\xx xx\yyy.exe'' /A /B"
ARRAY(str) a
ParseCommandLine(cl a)

int i
for i 0 a.len
,out a[i]
#6
With macro1
---------
out

str cl="This is a test my cute yes."
;str cl="''c:\xx xx\yyy.exe'' /A /B"
ARRAY(str) a
ParseCommandLine(cl a)

int i
for i 0 a.len
,out a[i]
----------
I get this output


This
is
a
test
my
cute
yes.


But with this macro2


out

str cl="This is a "test my" cute yes."
;str cl="''c:\xx xx\yyy.exe'' /A /B"
ARRAY(str) a
ParseCommandLine(cl a)

int i
for i 0 a.len
,out a[i]

I get this error output instead

Error in Testparamter with quote: missing ( after function name, or ; after statement.

Is it possible to get this output below with the above macro2 code? :?:

This
is
a
test my
cute
yes.

I'm trying to get the same parameter commands just like using a batch file or vbscript.
If possible I also would like to counter for the number of arguments passed and also error to cater if no arguments passed.
Thanks.
#7
Macro Macro1497
Code:
Copy      Help
str cl="This is a ''test my'' cute yes."
;or
str cl2=
;This is a "test my" cute yes.

Macro Macro1501
Code:
Copy      Help
ARRAY(str) a
ParseCommandLine(cl a)

;a.len is number of arguments

if a.len=0
,mes "error"
,ret -1 ;;an exit code
#8
Hello community.

I am totally new to QM and I have a question please:

How to use such macro function code from above post as a program function?



I don't get it. Even the help file didn't help me.


My example code would look like this:


test-commandline
Code:
Copy      Help
;/exe

Function ParseCommandLine
/
function $cmdLine ARRAY(str)&a

a=0
if(empty(cmdLine)) ret
int i n
word** w=CommandLineToArgvW(@cmdLine &n)
for(i 0 n) a[].ansi(w[i])

LocalFree w






ARRAY(str) a
ParseCommandLine(cl a)

int i
for i 0 a.len
    mes a[i]



test-commandline2
Code:
Copy      Help
run "$my qm$\test-commandline.exe" "/a /b /c"



- - -

EDIT

I read now quickmacros.com/forum/viewtopic.php?p=3524

2. In QM, create new function. To create new function, click menu File -> New -> New Function.


Question:

Do I really have to do this and utilize a second "document"?

Can't I just copy that function together with my code?

Now, if I will use "File -> New -> New Function", and if I compile to exe, would every needed functions be collect automatically and pack to the exe too?


Thanks Big Grin
#9
Yes need a second "document". These documents are not separate files.

In the newest QM beta also can be used sub-functions. Multiple private functions can be in single document.

QM now has function ExeParseCommandLine. Don't need this forum function.

Quote:Now, if I will use "File -> New -> New Function", and if I compile to exe, would every needed functions be collect automatically and pack to the exe too?
Yes.
#10
Thanks.

Of course, after posting I get how it works:


Function "document": ParseCommandLine
Code:
Copy      Help
/
function $cmdLine ARRAY(str)&a

a=0
if(empty(cmdLine)) ret
int i n
word** w=CommandLineToArgvW(@cmdLine &n)
for(i 0 n) a[].ansi(w[i])

Macro-1: (my program code, utilizing the above function. And "_command" will get me access to the command line parameters)
Code:
Copy      Help
;/exe

ARRAY(str) a
ParseCommandLine(_command a)

int i
for i 0 a.len
    mes a[i]

Macro-2: (my example program to try out Macro-1)
Code:
Copy      Help
run "$my qm$\Macro-1.exe" "/a /b /c"


Many thanks.
Now I understand a little bit more :mrgreen:
Now I go trying your other suggestions.
#11
with sub-function would be
Macro Macro2277
Code:
Copy      Help
str cl="a b c"
ARRAY(str) a
sub.ParseCommandLine(cl a)

int i
for(i 0 a.len) out a[i]

#sub ParseCommandLine
function $cmdLine ARRAY(str)&a

;Parses command line.
;Uses the same rules as most programs. <link "http://www.google.com/search?q=site%3amicrosoft.com%20Parsing%20C%2b%2b%20Command-Line%20Arguments">Read more</link>.

;cmdLine - command line.
;;;Can be path followed by command line. Then a[0] will be the path.
;a - receives command line arguments.


a=0
if(empty(cmdLine)) ret
int i n
word** w=CommandLineToArgvW(@cmdLine &n)
for(i 0 n) a[].ansi(w[i])

LocalFree w
#12
Hi Gintaras and all QM fellows!

Two questions, please:

1- Why the delay exe vs function?

2- How to pass parameters from a QM exe to a QM function?

Regards.

Macro Macro412
Code:
Copy      Help
out

long t1 t2 t3

t1=perf
run "$my qm$\Macro414.exe" "a b c"
t2=perf

Function18 "a b c"
t3=perf

out F"{(t2-t1)} microsec"
out F"{(t3-t2)} microsec"
out F"{(t2-t1)/(t3-t2)} times faster"

;148068 microsec
;47 microsec
;3150 times faster

Function Function18
Code:
Copy      Help
function str's

ARRAY(str) a
tok(s a)

int i
for i 0 a.len
,out a[i]

Macro Macro414 <- This is my exe
Code:
Copy      Help
ARRAY(str) a
ExeParseCommandLine(_command a)

int i
for i 0 a.len
,out a[i]

;BEGIN PROJECT
;main_function  Macro414
;exe_file  $my qm$\Macro414.exe
;icon  <default>
;manifest  $qm$\default.exe.manifest
;flags  6
;guid  {57C55193-8C16-4D76-A298-F6D3488E66DE}
;END PROJECT
#13
1. run depends on spe. Before insert spe 0.

2. To pass some data from exe to a function running in QM, not in that exe? Is that function running then (waiting for exe data), or it should be called when exe wants to pass data?
#14
Thanks for your help.

Gintaras Wrote:1. run depends on spe. Before insert spe 0.
It runs faster, but still 500 times slower than QM function Sad

Gintaras Wrote:2. To pass some data from exe to a function running in QM, not in that exe? Is that function running then (waiting for exe data), or it should be called when exe wants to pass data?
Yes, the QM func runs a QM exe and that exe returns some data to the first QM func waiting for those results.

In another post, you explained how to do the same with DLLs. It was amazing as we can combine easy development with QM and the power of c++. I would like to do something like this with a QM exe.

Regards.
#15
1. run can be replaced with CreateProcess, it is the fastest function to start a process, but probably will be not much faster. Also try run flag 0x30000. Or QM function StartProcess with first argument 0, it simply calls CreateProcess.

2.1. Does exe return data when it exits? Or it continues running after returning data? Should the QM function wait until exe exits?
2.2. What is data size?
2.3. Exe can store data in a file, or in registry, or in shared memory, etc. Then need a way to notify the QM function and synchronize data access. It depends on 2.1.
#16
1. ok. Thanks, I will try these options.

2.1. Yes, exe returns data and stops. And yes, QM func waits until exe exits.
2.2. Some integers will be ok.
2.3. The faster way would be the best.
#17
If need just to return a single integer:

Function this_is_my_exe
Code:
Copy      Help
;...
ret 5 ;;return an integer

;BEGIN PROJECT
;main_function  this_is_my_exe
;exe_file  $my qm$\this_is_my_exe.exe
;icon  <default>
;manifest  $qm$\default.exe.manifest
;flags  6
;guid  {D3960F15-7393-4411-8A6A-0731CBBF8E01}
;END PROJECT
Macro Macro2473
Code:
Copy      Help
int ec=CreateProcessSimple("''$my qm$\this_is_my_exe.exe'' /a ''b''" 1)
out ec
Function CreateProcessSimple
Code:
Copy      Help
;/
function# $cl [flags] ;;flags: 1 wait until exits

;Calls CreateProcess.
;Returns 0. If flag 1, returns the exit code.
;Error if fails.

;cl - program path, optionally followed by command line arguments.
;;;Program path can be enclosed in quotes. Should be enclosed if contains spaces.
;flags:
;;;1 - wait until exits and return the exit code.

;NOTES
;CreateProcess fails if would show UAC consent. Use run() instead.

;EXAMPLE
;int ec=CreateProcessSimple("''$my qm$\this_is_my_exe.exe'' /a ''b''" 1)
;out ec


opt noerrorshere 1

sel cl 2
,case ["$*","%*"] cl=_s.expandpath(cl)
,case ["''$*","''%*"] _s.expandpath(cl+1); _s-"''"; cl=_s

STARTUPINFOW si.cb=sizeof(si)
PROCESS_INFORMATION pi
if(!CreateProcessW(0 @cl 0 0 0 0 0 0 &si &pi)) end _s.dllerror
CloseHandle pi.hThread

if flags&1
,opt waitmsg -1
,wait 0 H pi.hProcess
,int R
,GetExitCodeProcess pi.hProcess &R

CloseHandle pi.hProcess
ret R
#18
Another way - create console exe, and run it with RunConsole2.
Function this_is_my_console_exe
Code:
Copy      Help
ExeConsoleWrite "some text"

;BEGIN PROJECT
;main_function  this_is_my_console_exe
;exe_file  $my qm$\this_is_my_console_exe.exe
;icon  <default>
;manifest  $qm$\default.exe.manifest
;flags  70
;guid  {D3960F15-7393-4411-8A6A-0731CBBF8E01}
;END PROJECT
Macro Macro2473
Code:
Copy      Help
str progPath.expandpath("$my qm$\this_is_my_console_exe.exe")
str s
RunConsole2 F"''{progPath}'' /a ''b''" s
out s
#19
Thanks for your help.
Best regards.
#20
Dear Gintaras,

I would appreciate it if you could advise on the modifications (if possible) in CreateProcessSimple so that this_is_my_exe returns a string value. I have tested it and it works with RunConsole2 but I would prefer CreateProcessSimple, if feasible.

Best regards.
#21
Let this_is_my_exe write the string in registry.
When CreateProcessSimple returns a success code, get the string from registry.
#22
Many thanks. Actually, this is what I did using a Qm registry (.ini) file.
#23
I want to use a file's right context menu entry to invoke, using this file, a qm .exe file, namely :
Registry entry : "C:\Documents and Settings\SES\My QM\Exe\GoToAFJ_Exe.exe" "%1"

I envisage a difficulty in obtaining the file's path (%1 above) in macro GoToAFJ_Exe. Any advice is welcome.
#24
OK, solution found using Macro414 above. ExeParseCommandLine proved to be very useful.


Forum Jump:


Users browsing this thread: 1 Guest(s)