Page 1 of 2

Args() - Returns command line parameters as array

Posted: 23 Aug 2014, 18:15
by SKAN
Args( CmdLine, Skip )
  • CmdLine: To parse scripts own parameters, pass DllCall( "GetCommandLine", "Str" )
    CmdLine can be anything, even imaginary parameters for mere test purposes.
  • Skip: The no. of parameters to skip ( from left ).
    For compiled scripts, the first parameter will be the executable which can be skipped by passing 1
    For uncompiled, it can be 2, that is A_AhkPath and A_ScriptFullpath will be skipped
    Additionally, a 'reloaded script' would have /restart in its parameters.

    argv[0] will contain the number of parameters retrieved. It will be a negative number if Skip > available

Code: Select all

Args( CmdLine := "", Skip := 0 ) {     ; By SKAN,  http://goo.gl/JfMNpN,  CD:23/Aug/2014 | MD:24/Aug/2014
  Local pArgs := 0, nArgs := 0, A := []
  
  pArgs := DllCall( "Shell32\CommandLineToArgvW", "WStr",CmdLine, "PtrP",nArgs, "Ptr" ) 

  Loop % ( nArgs ) 
     If ( A_Index > Skip ) 
       A[ A_Index - Skip ] := StrGet( NumGet( ( A_Index - 1 ) * A_PtrSize + pArgs ), "UTF-16" )  

Return A,   A[0] := nArgs - Skip,   DllCall( "LocalFree", "Ptr",pArgs )  
}
Usage example:
CmdLine := DllCall( "GetCommandLine", "Str" )
argv := Args( CmdLine )

; or simply
argv := Args( DllCall( "GetCommandLine", "Str" ) )

Test script:

Code: Select all

#Warn
#SingleInstance, Force

CmdLine := DllCall( "GetCommandLine", "Str" )
Skip    := ( A_IsCompiled ? 1 : 2 )

argv    := Args( CmdLine, Skip )

Msgbox % "Count = " argv[0] "`n1=" argv[1] "`n2=" argv[2] "`n3=" argv[3] "`n4=" argv[4] "`n5=" argv[5]

Re: Args() - Returns command line parameters as array

Posted: 26 Aug 2014, 08:41
by just me
I'm wondering about Args( CmdLine := "", Skip := 0 ). What will the funtion do if CmdLine is empty? Wouldn't it be better to call GetCommandLine() internally in this case?

Re: Args() - Returns command line parameters as array

Posted: 26 Aug 2014, 09:07
by SKAN
just me wrote:What will the funtion do if CmdLine is empty?
argv[0] will be 1
argv[1] will be fullpath of Autohotkey executable ( compiled or not )
just me wrote:Wouldn't it be better to call GetCommandLine() internally in this case?
Initially I put a ternary and then removed it. For a reloaded script, StringReplace is required to remove /restart from command line.

Re: Args() - Returns command line parameters as array

Posted: 26 Aug 2014, 11:48
by just me
MsgBox wrote:---------------------------
Empty CmdLine
---------------------------
Count = 2
1=C:\Program
2=Files\AutoHotkey\AutoHotkey.exe
3=
4=
5=
---------------------------
OK
---------------------------

Re: Args() - Returns command line parameters as array

Posted: 26 Aug 2014, 12:03
by SKAN
Whereas, my MsgBox wrote:---------------------------
test.ahk
---------------------------
Count = 1
1=D:\AutoHotkey\AutoHotkeyU64.exe
2=
3=
4=
5=
---------------------------
OK
---------------------------
No space in my A_AhkPath and hence it escaped me :)

Re: Args() - Returns command line parameters as array

Posted: 26 Aug 2014, 19:31
by joedf
:facepalm: SKAN -> :HeHe:

Re: Args() - Returns command line parameters as array

Posted: 28 Aug 2014, 18:13
by arcticir
I have a question, how to use DllCall ("GetCommandLine", "Str"), Get other processes on the command line?

Re: Args() - Returns command line parameters as array

Posted: 28 Aug 2014, 18:57
by SKAN
arcticir wrote:how to use DllCall ("GetCommandLine", "Str"), Get other processes on the command line?
Short answer: Create a thread in the target process and execute GetCommandLine() from that thread.
Here is a version from Sean: http://goo.gl/o8L3Q7
Let me know if you need help.

Re: Args() - Returns command line parameters as array

Posted: 29 Aug 2014, 07:47
by arcticir
Thanks.
but I can not find direct access to the command-line approach.
I have been using WMI to obtain,
it's just slower.

Code: Select all

CommandLine:=winmgmt("CommandLine","Where ProcessId = " PID "")

winmgmt(v,w:="",d:="Win32_Process",m:="winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2"){
	s:=[]
	for i in ComObjGet(m).ExecQuery("Select " (v?v:"*") " from " d  (w ? " " w :""))
		s.Insert(i[v])
	return s.MaxIndex()?(s.MaxIndex()=1?s.1:s):""
	}

Re: Args() - Returns command line parameters as array

Posted: 30 Aug 2014, 03:25
by Dougal
Thank you. I have wanted to process the command line parameters in a function, but couldn't work out how to (%0 etc return the function parameters not the script parameters). This will allow me to do what I was looking for.

Cheers

Re: Args() - Returns command line parameters as array

Posted: 30 Aug 2014, 05:12
by Dougal
Do you have a fix for the spaces in program name?

It also isn't returning parameters set in SciTE4AHK.

Re: Args() - Returns command line parameters as array

Posted: 30 Aug 2014, 06:31
by joedf
There might be an issue with SciTE4AHK...

Re: Args() - Returns command line parameters as array

Posted: 30 Aug 2014, 08:35
by Dougal
joedf wrote:There might be an issue with SciTE4AHK...
Possible. I also find that the parameters set in SciTE4AHK do not get passed to the script when using debugger. I didn't bother trying to run my test script for Args in debug mode for that reason.

Re: Args() - Returns command line parameters as array

Posted: 30 Aug 2014, 11:22
by joedf
Ahh Ok, I see..

Re: Args() - Returns command line parameters as array

Posted: 30 Aug 2014, 20:06
by Dougal
When I set "MyParameter" as parameter in SciTE4AHK, %1% returns it, but Args() does not - args[0] is always 2, and Args[1] and Args[2] are C:\Program and Files\AutoHotkey\AutoHotkey.exe respectively.
Looking at the script process via Process Explorer, the command line SciTE4AHK runs is

Code: Select all

"C:\Program Files\AutoHotkey\AutoHotkey.exe" /ErrorStdOut "D:\Dougal\Documents\AutoHotkey\Lib\args.ahk" MyParameter
so the parameter is being included in the autohotkey call, but DllCall( "Shell32\CommandLineToArgvW", "WStr",CmdLine, "PtrP",nArgs, "Ptr" ) isn't returning it for some reason.

Compiling the script and running with parameters also fails to return them. Scipt I am using to test:

Code: Select all

iPid := DllCall("GetCurrentProcessId")
MsgBox % iPID ; to check command line in Process Explorer, paraemetrs are present
msgbox %1% ; this returns "MyParameter"
msgbox % args()[args()[0]] ; this returns last part of AHK exe eg "Files\AutoHotkey\AutoHotkey.exe"
ExitApp

Args( CmdLine := "", Skip := 0 ) {     ; By SKAN,  http://goo.gl/JfMNpN,  CD:23/Aug/2014 | MD:24/Aug/2014
  Local pArgs := 0, nArgs := 0, A := []
 
  pArgs := DllCall( "Shell32\CommandLineToArgvW", "WStr",CmdLine, "PtrP",nArgs, "Ptr" )

  Loop % ( nArgs )
     If ( A_Index > Skip )
       A[ A_Index - Skip ] := StrGet( NumGet( ( A_Index - 1 ) * A_PtrSize + pArgs ), "UTF-16" )  

Return A,   A[0] := nArgs - Skip,   DllCall( "LocalFree", "Ptr",pArgs )  
}
I am using SciTE4AHK 3.0.06, with AHK 1.1.15.04 on Win7x64.

Cheers

Re: Args() - Returns command line parameters as array

Posted: 30 Aug 2014, 20:26
by SKAN
You need to insert CmdLine := DllCall( "GetCommandLine", "Str" ) just above your following lines and pass CmdLine as parameter to Args().
Dougal wrote:

Code: Select all

msgbox % args()[args()[0]] ; this returns last part of AHK exe eg "Files\AutoHotkey\AutoHotkey.exe"
ExitApp

Re: Args() - Returns command line parameters as array

Posted: 13 Oct 2014, 03:08
by Dougal
SKAN wrote:You need to insert CmdLine := DllCall( "GetCommandLine", "Str" ) just above your following lines and pass CmdLine as parameter to Args().
That fixed it, working beautifully now. Thanks for the help.

Re: Args() - Returns command line parameters as array

Posted: 17 Jan 2015, 02:55
by Dougal
To make it self contained, I now use this function in my library:

Code: Select all

aGetArgs(bAll := false) {
	/*
	Based on code By SKAN,  http://goo.gl/JfMNpN,  CD:23/Aug/2014 | MD:24/Aug/2014
	Modified by Dougal 17Jan15
	Returns array of strings, element 0 contains array count
	Includes commandline parts if bAll = true
	Otherwise strips non-parameter parts depending on how it was called:
		Compiled script
			removes compiled script name
		Script
			removes AutoHotkey executable and script name
		SciTe4AutoHotkey
			removes AutoHotkey executable, /ErrorStdOut parameter (if present) and script name
	*/
	sCmdLine := DllCall( "GetCommandLine", "Str" )
	pArgs := 0, nArgs := 0, aArgs := []
	pArgs := DllCall( "Shell32\CommandLineToArgvW", "WStr",sCmdLine, "PtrP",nArgs, "Ptr" )
	; get command line parts from memory
	Loop % (nArgs)
			aArgs.insert(StrGet(NumGet((A_Index - 1 ) * A_PtrSize + pArgs ), "UTF-16"))
	if not bAll { ; remove calling program parts
		; remove AutoHotkey.exe if not compiled script
		if not A_IsCompiled {
			aArgs.remove(1)
			nArgs -= 1
		}
		; remove /ErrorStdOut (run within SciTE4AutoHotkey)
		if (aArgs[1] = "/ErrorStdOut") {
			aArgs.remove(1)
			nArgs -= 1
		}
		; remove (compiled) script name
		aArgs.remove(1)
		nArgs -= 1
	}
	aArgs[0] := nArgs
	DllCall("LocalFree", "Ptr", pArgs)
	return, aArgs
}
It works with scripts launched by installed AutoHotkey, compiled scripts, and scripts run from within SciTe4. Having DllCall( "GetCommandLine", "Str" ) inside the function also works with scripts restarted as admin (used the above code to get the parameters to pass to the restarted script).

Cheers

Re: Args() - Returns command line parameters as array

Posted: 17 Mar 2015, 03:03
by Guest
I'm having an issue using this function, I need to pass whatever arguments my script receives to another application, the problem is that quotes are stripped.
example:

Code: Select all

<myscript.exe> /q /item:"c:\some folder"
will result in

Code: Select all

/q /item:c:\some folder
Is there a way to get the exact arguments that were passed to my script including quotes?

Re: Args() - Returns command line parameters as array

Posted: 17 Mar 2015, 11:27
by joedf
You have to escape your quotes when passing it to your program. Ie. ^" so for you it should be :

Code: Select all

<myscript.exe> /q /item:"^"c:\some folder^""