1

I'm trying to create a command in the command prompt, but use arguments like you can do with a function in another language.

For example, you can create a batch file in the C:\Windows\System32 folder and execute it in the command prompt by typing its name, creating a "command." This is very simple, though, and simply runs whatever the batch file contains.

My command I made is called toolbx, which has different useful shortcuts in the command prompt. But, I want to execute different tools by typing something like toolbx 1. Here's what it might look like.

toolbx [input received changing what tool you want to use] (e.g. 1)

In toolbx.bat

if %inputRecieved% == 1 goto 1

I'm not the best at explaining, so another example in Python might be:

def functionWithArgs (tool)

Executed as:

functionWithArgs(1)

As another summary:

I'm trying to make a command used in the command prompt with a batch file

I want the batch file to have arguments defined when the command is run (like the python example) that can be used as variables in the batch file.

Thank you in advance!

  • 2
    Type `set /?` and `call /?` and `cmd /?` for help. –  Mar 21 '20 at 21:13
  • you can use [functions](https://ss64.com/nt/syntax-functions.html), but it seems like what you're looking for is [macros](https://stackoverflow.com/a/60796197/12861751). – HaxAddict1337 Mar 22 '20 at 05:33

4 Answers4

1

It is your lucky day today, windows batch files do in fact support a feature called command-line parameters. Here is what you need to do:

set inputRecieved=%1
if "%inputRecieved%"=="1" goto label1
goto :eof

:label1
   blabla...

Have fun coding!

P.S.

Please note that the correct spelling of the word is "received", not "recieved".

Mike Nakis
  • 46,450
  • 8
  • 79
  • 117
  • Thank you! I completely missed that incorrect spelling of received. I will be looking further into command-line parameters. – matthewarthur1 Mar 22 '20 at 03:49
1

A technique has been developed using for loops that allows arguments to be captured when a variable is expanded - Batch Macros.

An outer for loop is used, which on the first iteration assigns a variable containing the argument values, and the inner loop/s proccess and act upon those values.

@echo off
Set "Macroname=For %%n in (1 2)Do if %%n==2 (Echo(!Args!)Else Set args="
Setlocal EnableDelayedExpansion
%Macroname% Hello World

The technique requires defining the macro variable in an environment where Delayed expansion is disabled, then using Setlocal EnableDelayedExpansion to enable the macro. ( Unless of course all ! expansion symbols are correctly escaped during macro definition for an environment where delayed expansion is enabled. )

Below is a template for batch macro's that builds an Args array and and proccesses switches that trail arguments. The purpose of the template is to allow quick scripting of advanced functions by having all the argument and switch handling logic ready to go, so that the meat of the function is all that needs to be scripted.

Args are returned to the array $Macroname_args[!$Macroname_args[i]!] where:
!$Macroname_args[i]! is a 0 indexed count of args.
Switches are returned in associated variables using the switch string as the index IE:
%MacroName% /A
Results in: !$Macroname_Switch[A]!==true
Or if a subarg is supplied:
%MacroName% /A sub arg
Results in: !$Macroname_Switch[A]!==sub arg

The macro uses Substring modification to seperate switches from args and process switches.
As such, arg or switch values containing the following characters:
= * / "
should be supplied in a substituted form:
{EQ} {AS} {FS} {DQ}, which are replaced using substitution built into the macro.

@Echo off

(Set \n=^^^

%= \n macro newline variable. Do not modify =%)
(Set LF=^


%= LF newline variable. Do not modify =%)

:# Example Switches for demonstrating concept. List used twice within macro switch handling. Define outside macro to
:# simplify maintainance.
 Set $MacroName_Switches="A" "B" "C" "D" "E" "Def"

 Set $MacroName=For %%n in (1 2)Do if %%n==2 (%\n%
  For /F "Tokens=1,2 Delims==" %%G in ('Set "$Macroname_Arg[" 2^^^> nul')Do Set "%%~G="%\n%
  For %%G in ( %$MacroName_Switches% )Do Set "$MacroName_Switch[%%~G]="%\n%
  If not "!$MacroName_args:* /=!" == "!$MacroName_args!" (%\n: build $MacroName.Args[!$MacroName_arg[i]!] array if args present =%
   Set "$MacroName_leading.args=!$MacroName_args:*/=!"%\n%
   For /F "Delims=" %%G in ("!$MacroName_leading.args!")Do Set "$MacroName_leading.args=!$MacroName_args:/%%G=!"%\n%
   Set ^"$MacroName_args=!$MacroName_args:"=!"%\n%
   Set "$MacroName_arg[i]=0"%\n%
   For %%G in (!$MacroName_leading.args!)Do (%\n%
    Set /A "$MacroName_arg[i]+=1"%\n%
    Set "$MacroName_arg[!$MacroName_arg[i]!]=%%~G"%\n%
    For %%i in ("!$MacroName_arg[i]!")Do (%\n%
     Set "$MacroName_arg[%%~i]=!$MacroName_arg[%%~i]:{FS}=/!"%\n%
     Set "$MacroName_arg[%%~i]=!$MacroName_arg[%%~i]:{AS}=*!"%\n%
     Set "$MacroName_arg[%%~i]=!$MacroName_arg[%%~i]:{EQ}==!"%\n%
     Set ^"$MacroName_arg[%%~i]=!$MacroName_arg[%%~i]:{DQ}="!"%\n%
    )%\n%
   )%\n%
  ) Else (%\n: remove doublequotes from args before switch processing switches =%
   Set ^"$MacroName_args=!$MacroName_args:"=!"%\n%
  )%\n%
  Set "$MacroName_LastSwitch="%\n%
  For /L %%L in (2 1 4)Do If "!$MacroName_LastSwitch!" == "" (%\n%
   If "!$MacroName_Args:~-%%L,1!" == " " Set "$MacroName_LastSwitch=_"%\n%
   If "!$MacroName_Args:~-%%L,1!" == "/" (%\n: Flag last switch true if no subargs; Works for character switches of up to 3 characters =%
    For /F "Delims=" %%v in ('Set /A "%%L-1"')Do Set "$MacroName_Switch[!$MacroName_Args:~-%%v!]=true"%\n%
    If not "!$MacroName_Args:/?=!." == "!$MacroName_Args!." Set "$MacroName_Switch[help]=true"%\n%
    Set "$MacroName_Args=!$MacroName_Args:~0,-%%L!"%\n%
    Set "$MacroName_LastSwitch=_"%\n%
   )%\n%
  )%\n%
  For %%G in ( %$MacroName_Switches% )Do If not "!$MacroName_args:/%%~G =!" == "!$MacroName_args!" (%\n%
   Set "$MacroName_Switch[%%~G]=!$MacroName_Args:*/%%~G =!"%\n%
   If not "!$MacroName_Switch[%%~G]:*/=!" == "!$MacroName_Switch[%%~G]!" (%\n%
    Set "$MacroName_Trail[%%~G]=!$MacroName_Switch[%%~G]:*/=!"%\n%
    For %%v in ("!$MacroName_Trail[%%~G]!")Do (%\n%
     Set "$MacroName_Switch[%%~G]=!$MacroName_Switch[%%~G]: /%%~v=!"%\n%
     Set "$MacroName_Switch[%%~G]=!$MacroName_Switch[%%~G]:/%%~v=!"%\n%
    )%\n%
    Set "$MacroName_Trail[%%~G]="%\n%
    If "!$MacroName_Switch[%%~G]:~-1!" == " " Set "$MacroName_Switch[%%~G]=!$MacroName_Switch[%%~G]:~0,-1!"%\n%
    If "!$MacroName_Switch[%%~G]!" == "" Set "$MacroName_Switch[%%~G]=true"%\n%
    If not "!$MacroName_Switch[%%~G]!" == "" If not "!$MacroName_Switch[%%~G]!" == "true" (%\n%
     Set "$MacroName_Switch[%%~G]=!$MacroName_Switch[%%~G]:{FS}=/!"%\n%
     Set "$MacroName_Switch[%%~G]=!$MacroName_Switch[%%~G]:{AS}=*!"%\n%
     Set "$MacroName_Switch[%%~G]=!$MacroName_Switch[%%~G]:{EQ}==!"%\n%
     Set ^"$MacroName_Switch[%%~G]=!$MacroName_Switch[%%~G]:{DQ}="!"%\n%
    )%\n%
   )%\n%
  )%\n: Insert Switch Assessment Below. Use conditional testing of valid switches to enact macro functions before $MacroName_args assignment =%
  REM INSERT COMMANDS BETWEEN THE ABOVE AND BELOW LINES TERMINATING EACH WITH \n VARIABLE %\n%
  %= EXAMPLE. Remove this line. =% Echo(!LF!Example: %%$Macroname%%!$Macroname_args!%\n%
  %= EXAMPLE. Remove this line. =% Set $Macroname_Arg[%\n%
  %= EXAMPLE. Remove this line. =% Set $Macroname_Switch[%\n%
 %= ESCAPE AMPERSANDS AND REDIRECTION CHARACTERS DURING MACRO DEFINITION. =%) Else Set $MacroName_args=


Setlocal enableDelayedExpansion

:# Proof of concept
%$Macroname% "{AS} param 1 {EQ} {DQ}https:{FS}{FS}stackoverflow.com{FS}posts{FS}60793679{DQ}" "param 2" /C one /D 12 /Def
%$Macroname% /B a b /E /Def "hello world & ^! > < | %%" /A 1 + 2 {EQ} 3 /Undefined switch

T3RR0R
  • 1,830
  • 2
  • 7
  • 17
1

You can use the macro style invented by @jeb, @dbenham and DosTips user @Ed Dyreen:

Definitions:

@echo off
SETLOCAL DISABLEDELAYEDEXPANSION

::Definitions
( set LF=^
%= EMPTY =%
)
set ^"NL=^^^%LF%%LF%^%LF%%LF%^^"

The whole purpose is to create a multiline variable. See the batch newline variable hack

Main Macro:

::Macro
ENDLOCAL &^
set $MACRO.Toolbx=FOR %%a in (args main) do if "%%a" == "main" (%NL%
    for %%A in (%payload%) do (%NL%
        %= MAIN MACRO HERE, END LINES WITH NL =%%NL%
    )%NL%
) ELSE SETLOCAL ENABLEDELAYEDEXPANSION ^& set args=,

exit /b

Save this as MACRO.Toolbx.bat. To use the macro inside your batch file:

call MACRO.Toolbx.bat
%$MACRO.Toolbx% COMMAND_LINE_ARGS

The macro uses a clever FOR loop to "catch" the arguments. Also, in order to catch arguments, DISABLEDELAYEDEXPANSION is necessary, which is inseparable from SETLOCAL. However, ENDLOCAL will destroy all user-defined variable in that range, but we need the newline definitions. Therefore, ENDLOCAL and the macro definition must be on the same line. This technique is called ENDLOCAL tunneling.

HaxAddict1337
  • 733
  • 1
  • 2
  • 17
1

sure [Complete path and file name] [Parameter1] [Parameter2] [and_so_on]

Is a space that separates parameters that can be expanded with %1 %2 %3...

You can expand all parameters with %* or up to 9 parameters individually for example:

%windir%\system32\toolbx.cmd Tool_1

note the parameter beign passed is: Tool_1

in the example below is beign used at line 2 where %1 expands: Tool_1

setlocal EnableDelayedExpansion
set tool=%1
set argument_1=Have
set argument_2=a
set argument_3=Nice
set argument_4=Day
CALL :Function_%tool% argument_1 argument_2 argument_3 argument_4
:: after Function_Tool_1 ends by reading the next GOTO :EOF after its Label,
:: will return to read instructions after this line
::
pause&&exit
::
:Function_Tool_1
echo. %argument_1% %argument_2% %argument_3% %argument_4% 
goto :EOF
::
::

NOTE:

When using CALL to call labels, you have to use a colon for example:

CALL :YourLabel

And after the label all the parameters or arguments separated with a space for example:

CALL :YourLabel param1 param2 param3 parampampam etc

I think the syntax for labels is the same as for variables.

You have to use a GOTO :EOF to end a function or procedure

See you don't use a colon when going to the label using GOTO for example:

GOTO YourLabel

but when using CALL is different, that is explained better typing:

EXIT /?

GOTO /?

& is used to separate instructions

&& is used to separate instructions inside a batch file as toolbx.cmd

Also note in the example above: %1 %2 %3 and %4 along the function could expand the variable name, for example:

echo. %1 %2 %3 %4

would echo: argument_1 argument_2 argument_3 argument_4

and using SETLOCAL EnableDelayedExpansion

!%1! could expand the value of the variable, for example:

echo. !%1! !%2! !%3! !%4!

would echo: Have a Nice Day

DKingpinCJ
  • 11
  • 4