You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
1. How a new process is created on *nix
On *nix, you launch a program using the execve API (or it's cousins execvp, execl, execlp, execle, and execvp). The interesting thing about these APIs is that they allow the caller to specify each of the command line arguments - the signature for execve is:
2.1 Example 1: Bash Shell
If you launch a program using the Bash shell command line, The Bash shell is responsible for turning the string provided by the user into the argv[] argument vector which is then passed to the program. For the Bash shell parameter parsing rules, the following links provide some information:
2.2 Example 2: Ubuntu Desktop Launcher Icon (GNOME→Nautilus)
In Ubuntu a desktop launcher icon can be created by right-clicking on the desktop and selecting "Create Launcher". This will generate a GNOME launch file ~/Desktop/launcher-name.desktop This is a text file you can browse (have a look at one). In this text file is a line starting with Exec= where the command and any command line parameters are.17
So what happens when you double-click on this desktop icon?
Ubuntu uses the GNOME Desktop Environment, which in turn uses the Nautilus File Manager. When you double-click on a desktop launcher icon, the Nautilus File Manager parses the Exec= command line in the ~/Desktop/launcher-name.desktop file and calls execve passing it argv[]. So to know how your command line parameters are parsed you need to look into how Nautilus parses command lines. There's some good documentation here:
2.3 Example 3: Kubuntu (KDE→Plasma)
Kubuntu is based on Ubuntu but uses the KDE Plasma Desktop instead of GNOME. So, to determine how your command line is parsed in that environment, you'll need to look into KDE application launchers. This starts to get complicated, because according to the documentation there are three: Kickoff, classic K menu, or Lancelot Launcher.18
It gets even more complicated, because it's possible to install both the KDE Plasma Desktop (kubuntu-desktop) as well as the GNOME desktop (ubuntu-desktop) on the same machine.
3. The *nix Parameter Parsing Rules
It all depends on who is processing your command line before the new process is created. On *nix, the parameters are parsed off by whatever program creates the new process.
This is all I have to say about *nix. The rest is about Windows.
Windows®
1. How a new process is created on Windows
On Windows, a new program is launched by calling the CreateProcess() API, which takes the command line as a string (the lpComandLine parameter to CreateProcess):
int CreateProcess( ..., lpComandLine, ... )
2. Passing Parameters to a new process on Windows
On Windows, the parameters are parsed off the command line after the new process is created, by the new process. It's considered the responsibility of the newly started application to call the GetCommandLine() API to retrieve the command line string and parse it (possibly using the CommandLineToArgvW() helper function).2
Windows
cmdline = "MyProg.exe Hello Goodbye Friday"
↓ create new process
CreateProcess(cmdline) →
→
New Process running MyProg.exe
↓ call
GetCommandLine()
↓ parse
argv[] =
MyProg.exe
Hello
Goodbye
Friday
3. How does a C/C++ program on Windows get argv[]?
The C/C++ compiler which compiles the program secretly adds extra code to the executable that retrieves and parses the command line to extract the parameters before calling WinMain (or main). Thus, for a C/C++ executable on Windows, the parameter parsing rules are determined by the C/C++ compiler that compiled the program.
4. Everyone Parses Differently
You'll get different results if you pass a command line to ShowParams.exe (written in C/C++), ShowParams.vbs (VBScript), or ShowParams.bat (batch file):
Sample Code:
ShowParams.c
#include "stdafx.h"
int main(int argc, char* argv[])
{
for (int i = 0; i < argc; ++i)
{
printf("param %d = ",i);
puts(argv[i]);
printf("\n");
}
return 0;
}
(Note: Avoid usingprintfwhen printing parameters, as the parameter may contain a % which would be interpreted byprintfas a conversion specifier. The program may crash with a bizarre error, such as "runtime error R6002 - Floating point not loaded".)
(Note: If we started this function withwmainor_tmainthenargv[]would point to wide character (unicode) strings. [Technically I'm not sure if they are UTF-16LE or UCS-2. I have 2 old posts discussing the basics of Unicode:
I also wrote a short book on Unicode:
ShowParamsC#.cs
using System;
namespace ShowParams
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("There are {0} program arguments", args.Length);
If Wscript.Arguments.Count = 0 Then
Wscript.echo "No parameters found"
Else
i=0
Do until i = Wscript.Arguments.Count
Parms = Parms & "Param " & i & " = " & Wscript.Arguments(i) & " " & vbcr
i = i+1
loop
Wscript.echo parms
End If
Parameters passed to ShowParams.exe are parsed by ShowParams.exe . The parameter parsing rules are determined by the C++ compiler that compiled ShowParams.exe
Parameters passed to ShowParams.bat are parsed by cmd.exe which is the program that processes batch files.
Parameters passed to ShowParams.vbs are parsed by WScript.exe which is the program that processes VBScript files3
(Note: If you only see the first letter of each parameter, the parameters may be in Unicode format.)
5. The C/C++ Parameter Parsing Rules
The documented program parameter parsing rules for Microsoft C/C++ compilers may be found by searching www.msdn.com for "Parsing C++ Command-Line Arguments".
There is separate documentation for each version of Microsoft's C/C++ compiler.
Fortunately the documentation is identical for all of them.
Unfortunately the documentation isn't complete.
The implimentation changed in 2008, which isn't documented.
Fortunately you're reading this.
Visual C++ Versions and Corresponding .dll
msvcr120.dll
—
Visual C++ 2013
—
(VC++ 12.0)
—
(released on October 17, 2013)
msvcr110.dl
—
Visual Studio 2012
—
(VC++ 11.0)
msvcr100.dll
—
Visual Studio 2010
—
(VC++ 10.0)
msvcr90.dll
—
Visual Studio 2008
—
(VC++ 9.0)
—
[new command line parsing]
msvcr80.dll
—
Visual Studio 2005
—
(VC++ 8.0)
msvcr71.dll
—
Visual C++ .NET 2003
—
(VC++ 7.1)
msvcr70.dll
—
Visual C++ .NET 2002
—
(VC++ 7.0)
msvcrt.dll
—
Visual C++ 6.0
—
(VC6)
Redistribution of the shared C runtime component in Visual C++
5.1 Here are the documented (and undocumented) rules:
Note: The Rules Changed in 2008
Arguments are delimited by white space, which is either a space or a tab.
The caret character (^) is not recognized as an escape character or delimiter. The character is handled completely by the command-line parser in the operating system before being passed to the argv array in the program. They are referring to the scenario discussed in sec. 6.2 below, where first the command line parser (cmd.exe) parses your command, handling such things as the escape character ^ , the redirection characters > & < , the pipe character | , the % character which may identify environment variables that need to be expanded (e.g. %PROGRAMFILES%), etc. The rules here describe how your C/C++ executable will parse the lpCommandLine that was passed to CreateProcess()by cmd.exe or whoever calls CreateProcess().
A string surrounded by double quotation marks ("string") is interpreted as a single argument, regardless of white space contained within. A quoted string can be embedded in an argument. The double quotes don't have to be around the whole parameter. A double quoted part may occur anywhere in the parameter.
A double quotation mark preceded by a backslash (\") is interpreted as a literal double quotation mark character (").
Backslashes are interpreted literally, unless they immediately precede a double quotation mark.
If an even number of backslashes is followed by a double quotation mark, one backslash is placed in the argv array for every pair of backslashes, and the double quotation mark is interpreted as a string delimiter.
If an odd number of backslashes is followed by a double quotation mark, one backslash is placed in the argv array for every pair of backslashes, and the double quotation mark is "escaped" by the remaining backslash, causing a literal double quotation mark (") to be placed in argv.
The missing undocumented rule has to do with how doubledouble quotes ("") are handled:
Prior to 2008:
If a closing " is followed immediately by another ", the 2nd " is accepted literally and added to the parameter.
After 2008
A double quote encountered outside a double quoted block starts a double quoted block.
A double quote encountered inside a double quoted block:
not followed by another double quote ends the double quoted block.
followed immediately by another double quote (e.g. ""), a single double quote is added to the output, and the double quoted block continues.
Parameters are always separated by a space or tab (multiple spaces/tabs OK)
If the parameter does not contain any spaces, tabs, or double quotes, then all the characters in the parameter are accepted as is (there is no need to enclose the parameter in double quotes).
Enclose spaces and tabs in a double quoted part
A double quoted part can be anywhere within a parameter
2n backslashes followed by a " produce n backslashes + start/end double quoted part
2n+1 backslashes followed by a " produce n backslashes + a literal quotation mark
n backslashes not followed by a quotation mark produce n backslashes
undocumented rules regarding double quotes:
Prior to 2008:
A " outside a double quoted block starts a double quoted block
A " inside a double quoted block ends the double quoted block
If a closing " is followed immediately by another ", the 2nd " is accepted literally and added to the parameter.
Post 2008:
Outside a double quoted block a " starts a double quoted block.
Inside a double quoted block a " followed by a different character (not another ") ends the double quoted block.
Inside a double quoted block a " followed immediately by another " (i.e. "") causes a single " to be added to the output, and the double quoted block continues.
backslashes not followed immediately by a double quotation mark are interpreted literally ↓ ↓ parameters are separated by spaces or tabs ┌───┐ a double quoted part can be anywhere within a parameter the space enclosed in double quotation marks is not a delimiter
a\\\"b c d ↑↑↑↑
a\"b ↑↑
c
d
2n+1 backslashes before" → n backslashes + a literal"
┌───┐↓ ↓ a\\\\"b c" d e ↑↑↑↑↑
a\\b c
d
e
2n backslashes followed by a"produce n backslashes + start/end double quoted part. ↓ ↓ parameters are separated by spaces or tabs ┌───┐ a double quoted part can be anywhere within a parameter the space enclosed in double quotation marks is not a delimiter
""while in a double quoted part → accept 2nd"literally, double quoted part continues
┌─────────────────┐ """CallMeIshmael""" b c ↑↑ ↑↑
"CallMeIshmael" ↑ ↑
b
c
"Begin double quoted part.
""while in a double quoted part → accept 2nd"literally, double quoted part continues
"not followed by another"(i.e. not"") while in a double quoted part → ends the double quoted part
Parameters are delimited by spaces or tabs.
┌───────────────────┐ """Call Me Ishmael""" ↑↑ ↑↑
"Call Me Ishmael" ↑ ↑
"Begin double quoted part.
""while in a double quoted part → accept 2nd"literally, double quoted part continues
"not followed by another"(i.e. not"") while in a double quoted part → ends the double quoted part
┌──┐ ┌┐ """"Call Me Ishmael"" b c ↑↑
"Call ↑
Me
Ishmael
b
c
"Begin double quoted part.
""while in a double quoted part → accept 2nd"literally, double quoted part continues
"not followed by another"(i.e. not"") in a double quoted part → ends the double quoted part
Parameters are delimited by spaces or tabs.
(note""outside of double quoted block begins and then immediately ends a double quoted part.)
(pre 2008)
Command-Line Input
argv[1]
argv[2]
argv[3]
Comment
┌─────┐ "a b c"" ↑↑
a b c" ↑
""while in a double quoted part → end double quoted part and accept 2nd"literally
┌┐ ┌┐ """CallMeIshmael""" b c ↑↑ ↑↑
"CallMeIshmael" ↑ ↑
b
c
"Begin double quoted part. ""while in a double quoted part → end double quoted part and accept 2nd"literally
┌┐ ↓ ↓ ┌┐ """Call Me Ishmael""" ↑↑ ↑↑
"Call ↑
Me
Ishmael" ↑
Parameters are delimited by spaces or tabs. "Begin double quoted part. ""while in a double quoted part → end double quoted part and accept 2nd"literally
┌┐ ┌───────────────┐ """"Call Me Ishmael"" b c ↑↑ ↑↑
"Call Me Ishmael" ↑ ↑
b
c
Parameters are delimited by spaces or tabs. "Begin double quoted part. ""while in a double quoted part → end double quoted part and accept 2nd"literally
...""""Call me Ishmael""""... ↑↑↑↑↑↑↑↑↑↑ quote #1: Begin double quoted part──────┘├┘├┘ │├┘││ quotes #2 & 3: Skip 1st " take 2nd " ────┘ │ ││ ││ quote #4: End double quoted part───────────┘ ││ ││ ││ ││ quote #5: Begin double quoted part─────────────────────────┘│ ││ quotes #6 & 7: Skip 1st " take 2nd " ───────────────────────┘ ││ quote #8: End double quoted part──────────────────────────────┘│ Assuming this isn't another " ───────────────────────┘
>ShowParams.exe """"Call Me Ishmael""""
param 1 = "Call
param 2 = Me
param 3 = Ishmael"
an alternative method is
>ShowParams.exe \"Call Me Ishmael\"
param 1 = "Call
param 2 = Me
param 3 = Ishmael"
(pre 2008)
How quadruple double quotes are parsed (pre 2008)
...""""Call me Ishmael""""... ↑↑↑↑↑↑↑↑↑ quote #1: Begin double quoted part──────┘│││ │││││ quote #2: End double quoted part─────────┘││ │││││ quote #3: and accept this " literally─────┘│ │││││ quote #4: Begin another double quoted part─┘ │││││ │││││ quote #5: End double quoted part───────────────────────────┘││││ quote #6: and accept this " literally───────────────────────┘│││ quote #7: Begin double quoted part───────────────────────────┘││ quote #8: End double quoted part──────────────────────────────┘│ If this was a double quote we'd accept it literally──┘
>ShowParams.exe """"Call Me Ishmael""""
param 1 = "Call Me Ishmael"
Note quotes #7,#8 are not necessary. They contribute nothing.
>ShowParams.exe """"Call Me Ishmael""
param 1 = "Call Me Ishmael"
an alternative method is
>ShowParams.exe "\"Call Me Ishmael\""
param 1 = "Call Me Ishmael"
The following algorithm was reverse engineered by disassembling a small C program compiled using Microsoft Visual C++ and examining the disassembled code.
for the actual diasssembled code with annotations.
note if odd number of backslashes, we ignore last backslash and begin again.
1.
Parse off parameter 0 (the program filename)
•
The entire parameter may be enclosed in double quotes (it handles double quoted parts) (Double quotes are necessary if there are any spaces or tabs in the parameter)
•
There is no special processing of backslashes (\)
2.
Parse off next parameter:
a.
Skip over multiple spaces/tabs between parameters
LOOP
b.
Count the backslashes (\). Let m = number of backslashes. (m may be zero.)
IF even number of backslashes (or zero)
c.
IF next character following m backslashes is a double quote:
Even number of backslashes?
Yes. If we're not in a double quoted part, " begins a double quoted part.
Yes. If we're in a double quoted part, "" skip 1st take 2nd "
If m is even (or zero)
if currently in a double quoted part
IF next character is also a "
move to next character (the 2nd ". This character will be added to the parameter.)
ELSE
set flag to not add this " character to the parameter
toggle double quoted part flag (end double quoted part)
ENDIF
else
set flag to not add this " character to the parameter
endif
Endif
ENDIF
ENDIF
Add backslashes to output
m = m/2 (floor divide e.g. 0/2=0, 1/2=0, 2/2=1, 3/2=1, 4/2=2, 5/2=2, etc.)
for the actual diasssembled code with annotations.
6. Who Calls CreateProcess?
So far we've talked about parsing the command line that got passed as the lpCommandLine parameter to CreateProcess(). But who calls CreateProcess? One possibility is you could write a small program which calls CreateProcess() passing it a command line.
Another possibility is you could open a Command Prompt window and type in a command:
6.2 Command Prompt Window → CreateProcess()
The command prompt window is program cmd.exe (go to START → RUN, enter "cmd"). Program cmd.exe displays the command prompt window, reads your command, and parses it handling such things as redirection characters (>) & (<), the pipe character (|), the escape character (^), identifying and expanding Environment Variables (e.g. %PROGRAMFILES%), etc. Then cmd.exe calls CreateProcess(), passing it a command line.4
parse and process command handling special characters like ^ < > | %
create a command line
cmdline = "ShowParams.exe Hello Goodbye Friday"
↓ create new process
CreateProcess(cmdline) →
→
New Process running ShowParams.exe
↓ call
GetCommandLine()
↓ parse
argv[] =
ShowParams.exe
Hello
Goodbye
Friday
Note here your command line is parsed twice:
by the Command Prompt Window (cmd.exe)
by ShowParams.exe
So if you want to get a parameter on the command line to ShowParams.exe, you first need to get it through the cmd.exe parser, then through the parser the Microsoft C/C++ compiler added to ShowParams.exe
7. The cmd.exe Command Prompt Parsing Rules
The command prompt window is program cmd.exe5 (go to START → RUN, enter "cmd"). The command prompt window.
Escape Character
^ is the escape character for commands passed to cmd.exe
Double Quotes:
An unescaped " will begin or end a double quoted part, and the double quote will be included as part of the parameter.
^" outside a double quoted part will insert a " but will not start a double quoted part.
Environment variables are expanded both inside and outside double quotes.
Outside Double Quotes:
Use ^ outside double quotes to escape < > & | ^
to insert < use ^<
to insert > use ^>
to insert | use ^|
to insert ^ use ^^
to insert " and begin a double quoted part use "
to insert " and not begin a double quoted part use ^"
sometimes it may be necessary to also escape ( ) @ !
It's OK to escape everything
Note ^ is also the line continuation character.
Inside Double Quotes:
Inside Double Quotes, everything is taken literally
^" gives ^" but does not end a double quoted part
Environment variable expansion is still performed inside double quotes
Percent Sign:
If your command line will be placed in a batch file, double the % character6
Note: The result is what gets passed as part of the lpCommandLine argument to the CreateProcess() API. The newly created process still needs to retrieve the lpCommandLine string and parse off the parameters using it's own parsing rules (e.g. if it's a C/C++ program, it will use the Microsoft C/C++ parameter parsing rules to create the argv[] vector. See Putting It Together below for more on this).
The " character has been escaped with ^ so it doesn't start a double quoted part when cmd.exe parses it. Then ^" is escaped by \ so ShowParams.exe will see it as a literal " (Microsoft C/C++ parsing rules) The result is: \^"→ cmd.exe parses to give\"→ ShowParams.exe parses to give →"
▲
Note if this command line is to be put in a batch file, the % will need to be doubled.
Outside of Double Quotes It's OK to Escape Everything
The " character has been escaped with ^ so it doesn't start a double quoted part when cmd.exe parses it. Then ^" is escaped by \ so ShowParams.exe will see it as a literal " (Microsoft C/C++ parsing rules) \ itself is escaped by ^ just for the heck of it (it's OK to escape everything). The result is: ^\^"→ cmd.exe parses to give\"→ ShowParams.exe parses to give →"
▲
Note if this command line is to be put in a batch file, the % will need to be doubled.
Outside a double quoted part, when not escaped with a ^, a double quote " produces a double quote " and begins a double quoted part
"
Inside a double quoted part, a double quote " produces a double quote " and ends the double quoted part
The " character is always included as part of the parameter
↑
Note the " character has been left out of the sequence as it would end the double quoted part. (You can't escape a " while in a double quoted part. The closest we could get would be to use ^" which would give us a ^" and not end the double quoted part.)
▲
Note if this command line is to be put in a batch file, the % will need to be doubled.
cmd.exe command line parser interprets ^& as an escaped & character so it does not interpret this as “start a new command.” (It's possible to put more than one DOS command on a command line by separating them with the & character.)
2.
C/C++ command line parser receives this. There are no double quotes for it to process.
3.
C/C++ command line parser parses off the command line parameters into the argv[] array.
cmd.exe command line parser interprets the first " as “Start a double quoted part” and the second " as “End the double quoted part.” cmd.exe does not remove the double quote characters. (Note that these double quotes are not escaped with the ^ character, which is the escape character for cmd.exe. Also note the \ character is treated as an ordinary character by cmd.exe)
cmd.exe command line parser interprets ^& as an escaped & character so it does not interpret this as “start a new command.” (It's possible to put more than one DOS command on a command line by separating them with the & character.)
2.
C/C++ command line parser receives this. The C/C++ parser interperts \" as an escaped double quote so neither one starts a double quoted part.
3.
C/C++ command line parser parses off the command line parameters into the argv[] array.
cmd.exe command line parser interprets ^" as an escaped " character so it does not start or end a double quoted part.
cmd.exe command line parser interprets ^& as an escaped & character so it does not interpret this as “start a new command.” (It's possible to put more than one DOS command on a command line by separating them with the & character.)
2.
C/C++ command line parser receives this. The C/C++ parser interperts " as “start or end a double quoted part” and the double quotes are removed.
3.
C/C++ command line parser parses off the command line parameters into the argv[] array.
cmd.exe command line parser interprets ^" as an escaped " character so it does not interpret this as “Start a double quoted part.”
cmd.exe command line parser interprets ^& as an escaped & character so it does not interpret this as “Start a new command.” (It's possible to put more than one DOS command on a command line by separating them with the & character.)
2.
C/C++ command line parser receives this. The C/C++ parser interperts \" as an escaped double quote so they do not start a double quoted part.
3.
C/C++ command line parser parses off the command line parameters.
It gets harder when double quotes are not escaped with ^ as cmd.exe will now interpert them as “Start or end a double quoted part.”
cmd.exe command line parser interprets the first " as “Start a double quoted part” and the second " as “End the double quoted part.” cmd.exe does not remove the double quote characters.
Inside the double quoted part cmd.exe interprets all characters literally, including ^ and &
2.
C/C++ command line parser receives this. The parser interperts the first " as “Start a double quoted part” and the second " as “End the double quoted part.” The double quotes are removed.
3.
C/C++ command line parser parses off the command line parameters into the argv[] array.
cmd.exe command line parser interprets ^" as an escaped " character so it does not start or end a double quoted part.
cmd.exe command line parser interprets ^& as an escaped & character so it does not interpret this as “start a new command.” (It's possible to put more than one DOS command on a command line by separating them with the & character.)
2.
C/C++ command line parser receives this. The parser interperts " as “start or end a double quoted part” and the double quotes are removed.
3.
C/C++ command line parser parses off the command line parameters into the argv[] array.
cmd.exe command line parser interprets ^" as an escaped " character so it does not start or end a double quoted part. The ^ is removed. The " is not removed.
2.
The C/C++ command line parser receives this.
The C/C++ command line parser interperts the first " as “Start a double quoted part” and the double quote is removed.
The C/C++ command line parser interperts \\\" inside the double quoted part as a literal \"
The C/C++ command line parser interperts the ending " as “End the double quoted part” and the double quote is removed.
3.
The C/C++ command line parser fills the argv[] array with the result.
cmd.exe command line parser interprets ^" as an escaped " character so it does not start or end a double quoted part. The ^ is removed. The " is not removed.
cmd.exe command line parser interprets \ as an ordinary character.
cmd.exe command line parser interprets ^" as an escaped " character so it does not start or end a double quoted part. The ^ is removed. The " is not removed.
cmd.exe command line parser interprets Bed Bath Beyond\ as ordinary characters.
cmd.exe command line parser interprets ^" as an escaped " character so it does not start or end a double quoted part. The ^ is removed. The " is not removed.
cmd.exe command line parser interprets ^" as an escaped " character so it does not start or end a double quoted part. The ^ is removed. The " is not removed.
2.
The C/C++ command line parser receives this.
The C/C++ command line parser interperts the first " as “Start a double quoted part” and the double quote is removed.
The C/C++ command line parser interperts \" inside the double quoted part as a literal "
The C/C++ command line parser interperts \" inside the double quoted part as a literal "
The C/C++ command line parser interperts the ending " as “End the double quoted part” and the double quote is removed.
3.
The C/C++ command line parser fills the argv[] array with the result.
8.1
How To Pass A Parameter to: a C/C++ Program from the Command Line
A Simplified method: (2016)
The trick is to enclose parameters with ^" instead of just "
e.g. instead of:
"Bed Bath Beyond"
use
^"Bed Bath Beyond^"
The command processor cmd.exe will strip off the ^ and won't start any double quoted parts.
Simplified method steps:
Start with the parameter you want
Escape with ^ all these special characters: ^ < > | & ( ) "
i.e. replace ^ with ^^
replace < with ^<
replace > with ^>
replace | with ^|
replace & with ^&
replace ( with ^(
replace ) with ^)
replace " with ^"
Then, for all ^", double the number of \ immediately preceeding the ^" (there may be zero, in which case do nothing).
And for all ^", add a preceeding \
Steps 3 & 4 combined are:
replace ^" with \^"
replace \^" with \\\^"
replace \\^" with \\\\\^"
replace \\\^" with \\\\\\\^"
etc.
Add a leading and trailing ^"
Example 8.1: Command Line to C/C++ Program
Example 8.1: Bed Bath & Beyond
Parameter
1.
Start with the parameter you want (parameter includes spaces)
Bed Bath & Beyond
2.
Escape with ^ all special characters: ^ < > | & ( ) "
i.e. replace ^ with ^^
replace < with ^<
replace > with ^>
replace | with ^|
replace & with ^&
replace ( with ^(
replace ) with ^)
replace " with ^"
Bed Bath ^& Beyond ↑
3.
For all ^", double the number of \ immediately preceeding the ^" (there may be zero)
no \^" in parameter
4.
For all ^", add a leading \
no ^" in parameter
5.
Add a leading and trailing ^"
^"Bed Bath ^& Beyond^" ↑↑ ↑↑
6.
if this will be placed in a batch file, double the % characters
no % in parameter
Result: To get desired parameter use this:
^"Bed Bath ^& Beyond^"
Now examine how this parameter gets parsed:
A.
cmd.exe treats ^ as escape character and removes them.
cmd.exe finds no double quoted parts because all " are escaped with ^
^"Bed Bath & Beyond^" ↓ ↓
B.
cmd.exe passes this as parameter to the C/C++ program
"Bed Bath & Beyond"
C.
C/C++ program sees this as a double quoted parameter.
┌─────────────────┐ "Bed Bath & Beyond" ↓ ↓
D.
C/C++ program applies the rule 2n+1 backslashes followed by a "
produce n backslashes + a literal "
no \" in parameter
E.
Result is the desired parameter we started with
Bed Bath & Beyond
Sample Test File:
Example 8.2: Bed "Bath" & Beyond
Parameter
1.
Start with the parameter you want (parameter includes spaces)
Bed "Bath" & Beyond
2.
Escape with ^ all special characters: ^ < > | & ( ) "
i.e. replace ^ with ^^
replace < with ^<
replace > with ^>
replace | with ^|
replace & with ^&
replace ( with ^(
replace ) with ^)
replace " with ^"
Bed ^"Bath^" ^& Beyond ↑_ ↑_ ↑_
3.
For all ^", double the number of \ immediately preceeding the ^" (there may be zero)
no \^" in parameter
4.
For all ^", add a leading \
Bed \^"Bath\^" ^& Beyond ↑__ ↑__
5.
Add a leading and trailing ^"
^"Bed \^"Bath\^" ^& Beyond^" ↑↑ ↑↑
6.
if this will be placed in a batch file, double the % characters
no % in parameter
Result: To get desired parameter use this:
^"Bed \^"Bath\^" ^& Beyond^"
Now examine how this parameter gets parsed:
A.
cmd.exe treats ^ as escape character and removes them.
cmd.exe finds no double quoted parts because all " are escaped with ^
^"Bed \^"Bath\^" ^& Beyond^" ↓ ↓ ↓ ↓ ↓
B.
cmd.exe passes this as parameter to the C/C++ program
"Bed \"Bath\" & Beyond"
C.
C/C++ program sees this as a double quoted parameter.
Note that all " inside the parameter are escaped with \
C/C++ program applies the rule 2n+1 backslashes followed by a "
produce n backslashes + a literal quotation mark
\" becomes "
\\\" becomes \"
(Bed) <Bath> & \"Beyond\" | \\\"Kohl^s -- -- ----
E.
Result is the desired parameter we started with
(Bed) <Bath> & "Beyond" | \"Kohl^s
Sample Test File:
Example 8.5: &<>^|()@!"
Parameter
Start with the parameter you want
(parameter includes a space)
&<>^|()@!"
1.
Escape with ^ all special characters: ^ < >| & ( ) "
i.e. replace ^ with ^^
replace < with ^<
replace > with ^>
replace | with ^|
replace & with ^&
replace ( with ^(
replace ) with ^)
replace " with ^"
^&^<^>^^^|^(^)^@^!^" ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑
2.
For all ^", double the number of \ immediately preceeding the ^" (there may be zero)
no \^" in parameter
3.
For all ^", add a leading \
^&^<^>^^^|^(^)^@^!\^" ↑
4.
Add a leading and trailing ^"
^"^&^<^>^^^|^(^)^@^!\^"^" ↑↑ ↑↑
5.
if this will be placed in a batch file, double the % characters
no % in parameter
Result: To get desired parameter use this:
^"^&^<^>^^^|^(^)^@^!\^"^"
Now examine how this parameter gets parsed:
A.
cmd.exe treats ^ as escape character and removes them.
cmd.exe finds no double quoted parts because all " are escaped with ^
^"^&^<^>^^^|^(^)^@^!\^"^" ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓
B.
cmd.exe passes this as parameter to the C/C++ program
"&<>^|()@!\""
C.
C/C++ program sees this as a double quoted parameter.
Note all " inside the double quoted parameter are escaped with \
┌───────────┐ "&<>^|()@!\"" ↓ ↓
D.
C/C++ program applies the rule 2n+1 backslashes followed by a "
produce n backslashes + a literal quotation mark
\" becomes "
&<>^|()@!\" --
E.
Result is the desired parameter we started with
&<>^|()@!"
Sample Test File:
The following older examples show the harder way of figuring out what to use as parameters.
Example 8.6: Command Line to C/C++ Program
Example 8.6a: &<>^|()@ !
Parameter
Start with the parameter you want
(parameter includes a space)
&<>^|()@ !
1.
Apply the Microsoft C/C++ parsing rules
a.
replace:
literal " with \"
literal \" with \\\"
literal \\" with \\\\\"
nothing to replace
b.
enclose the whole parameter in double quotes
(because there's a space in the parameter)
┌──────────┐ "&<>^|()@ !" ↑ ↑
2.
Apply the Command Prompt parsing rules (cmd.exe)
a.
determine what cmd.exe will see as the quoted parts
┌──────────┐ "&<>^|()@ !"
b.
escape the special characters not in double quoted parts:
( the escape character for cmd.exe is ^ )
Nothing to escape because it's all in a double quoted part
(as seen by cmd.exe)
c.
if this will be placed in a batch file, double the % characters
no % in parameter
Result: To get desired parameter use this:
"&<>^|()@ !"
Example 8.6b: &<>^|()@ !
Parameter
Start with the parameter you want
(same as example 1a)
&<>^|()@ !
1.
Apply the Microsoft C/C++ parsing rules
a.
replace:
literal " with \"
literal \" with \\\"
literal \\" with \\\\\"
nothing to replace
b.
enclose spaces in double quotes
(A double quoted part can be anywhere within a parameter)
&<>^|()@" "! ↑ ↑
2.
Apply the Command Prompt parsing rules (cmd.exe)
a.
determine what cmd.exe will see as the quoted parts
┌─┐ &<>^|()@" "!
b.
escape the special characters not in double quoted parts:
( the escape character for cmd.exe is ^ )
┌─┐ ^&^<^>^^^|^(^)^@" "^! ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑
c.
if this will be placed in a batch file, double the % characters
no % in parameter
Result: To get desired parameter use this:
^&^<^>^^^|^(^)^@" "^!
Sample Test File:
Example 8.7: Command Line to C/C++ Program
Example 8.7: &<>^|@()!"&<>^|@() !
Parameter
Start with the parameter you want
&<>^|@()!"&<>^|@()!
1.
Apply the Microsoft C/C++ parsing rules
a.
replace:
literal " with \"
literal \" with \\\"
literal \\" with \\\\\"
&<>^|@()!\"&<>^|@()! ↑
b.
enclose the whole parameter in double quotes
"&<>^|@()!\"&<>^|@()!" ↑ ↑
2.
Apply the Command Prompt parsing rules (cmd.exe)
a.
determine what cmd.exe will see as the quoted parts
┌──────────┐ ┌─── "&<>^|()@!\"&<>^|@()!"
we have a problem in that the final " is interpreted by cmd.exe as opening a double quoted part. To avoid this, escape that last " ( the escape character for cmd.exe is ^ )
┌──────────┐ "&<>^|()@!\"&<>^|@()!^" ↑
b.
escape the other special characters not in double quoted parts:
( the escape character for cmd.exe is ^ )
if this will be placed in a batch file, double the % characters
no % in parameter
Result: To get desired parameter use this:
"&<>^|@()!\"^&^<^>^^^|@()!^"
Another way to get the same result would be at step 1b don't enclose the parameter in double quotes, then escape all special characters including the double quote so it doesn't start a double quoted part.
we have a problem in that the final " is interpreted by cmd.exe as opening a double quoted part. To avoid this, escape that last " ( the escape character for cmd.exe is ^ )
┌─┐ ┌───────────┐ "\"&<>^|@() !\"&<>^|@() !\"^" ↑
b.
escape the special characters not in double quoted parts:
( the escape character for cmd.exe is ^ )
if this will be placed in a batch file, double the % characters
no % in parameter
Result: To get desired parameter use this:
"\"^&^<^>^^^|@() !\"&<>^|@() !\"^"
Another way to get the same result would be at step 2a just escape all special characters including all double quotes so there are no double quoted parts.
once again we have a problem in that the final " is interpreted by cmd.exe as opening a double quoted part. To avoid this, escape that last " ( the escape character for cmd.exe is ^ )
if this will be placed in a batch file, double the % characters
no % in parameter
Result: To get desired parameter use this:
\"&<>^|@()" "!\"^&^<^>^^^|@()" "!\^"
Another way to get the same result would be at step 2a just escape all special characters including all double quotes so there are no double quoted parts.
Start with the parameter you want (parameter includes double quotes and a space)
"C:\TEST A\"
1.
Apply the Microsoft C/C++ parsing rules
a.
replace:
literal " with \"
literal \" with \\\"
literal \\" with \\\\\"
\"C:\TEST A\\\" ↑ ↑↑
b.
enclose the whole parameter in double quotes
(because there's a space in the parameter)
┌───────────────┐ "\"C:\TEST A\\\"" ↑ ↑
2.
Apply the Command Prompt parsing rules (cmd.exe)
a.
determine what cmd.exe will see as the quoted parts
┌─┐ ┌┐ "\"C:\TEST A\\\""
b.
escape the special characters not in double quoted parts:
( the escape character for cmd.exe is ^ )
No special characters to escape
(as seen by cmd.exe)
c.
if this will be placed in a batch file, double the % characters
no % in parameter
Result: To get desired parameter use this:
"\"C:\TEST A\\\""
Another way to get the same result would be at step 2a just escape all special characters including all double quotes so there are no double quoted parts.
^"\^"C:\TEST A\\\^"^" ↑ ↑ ↑ ↑
Example 8.9b: "C:\TEST A\"
Parameter
Start with the parameter you want (same as 4a)
"C:\TEST A\"
1.
Apply the Microsoft C/C++ parsing rules
a.
replace:
literal " with \"
literal \" with \\\"
literal \\" with \\\\\"
\"C:\TEST A\\\" ↑ ↑↑
b.
enclose spaces in double quotes
(A double quoted part can be anywhere within a parameter)
\"C:\TEST" "A\\\" ↑ ↑
2.
Apply the Command Prompt parsing rules (cmd.exe)
a.
determine what cmd.exe will see as the quoted parts
┌───────┐ ┌────┐\"C:\TEST" "A\\\"
b.
escape the special characters not in double quoted parts:
( the escape character for cmd.exe is ^ )
It's all in double quoted parts.
(as seen by cmd.exe)
c.
if this will be placed in a batch file, double the % characters
no % in parameter
Result: To get desired parameter use this:
\"C:\TEST" "A\\\"
Another way to get the same result would be at step 2a just escape all special characters including all double quotes so there are no double quoted parts.
\^"C:\TEST^" ^"A\\\^" ↑ ↑ ↑ ↑
Sample Test File:
Example 8.10: Command Line to C/C++ Program
Example 8.10a: "C:\TEST %&^ A\"
Parameter
Start with the parameter you want
"C:\TEST %&^ A\"
1.
Apply the Microsoft C/C++ parsing rules
a.
replace:
literal " with \"
literal \" with \\\"
literal \\" with \\\\\"
\"C:\TEST %&^ A\\\" ↑ ↑↑
b.
enclose the whole parameter in double quotes
┌───────────────────┐ "\"C:\TEST %&^ A\\\""
2.
Apply the Command Prompt parsing rules (cmd.exe)
a.
determine what cmd.exe will see as the quoted parts
┌─┐ ┌┐ "\"C:\TEST %&^ A\\\""
b.
escape the special characters not in double quoted parts:
( the escape character for cmd.exe is ^ )
┌─┐ ┌┐ "\"C:\TEST ^%^&^^ A\\\"" ↑ ↑ ↑
c.
if this will be placed in a batch file, double the % characters
┌─┐ ┌┐ "\"C:\TEST ^%%^&^^ A\\\"" ↑
Result: To get desired parameter use this:
"\"C:\TEST ^%%^&^^ A\\\""
Another way to get the same result would be at step 2a just escape all special characters including all double quotes so there are no double quoted parts.
^"\^"C:\TEST %^&^^ A\\\^"^" ↑ ↑ ↑ ↑ ↑ ↑
c.
and if this will be placed in a batch file, double the % characters
^"\^"C:\TEST %%^&^^ A\\\^"^" ↑
Example 8.10b: "C:\TEST %&^ A\"
Parameter
Start with the parameter you want (same as 5a)
"C:\TEST %&^ A\"
1.
Apply the Microsoft C/C++ parsing rules
a.
replace:
literal " with \"
literal \" with \\\"
literal \\" with \\\\\"
\"C:\TEST %&^ A\\\" ↑ ↑↑
b.
enclose spaces in double quotes
(A double quoted part can be anywhere within a parameter)
┌─┐ ┌─┐ \"C:\TEST" "%&^" "A\\\" ↑ ↑ ↑ ↑
2.
Apply the Command Prompt parsing rules (cmd.exe)
a.
determine what cmd.exe will see as the quoted parts
┌───────┐ ┌───┐ ┌────┐ \"C:\TEST" "%&^" "A\\\"
b.
escape the special characters not in double quoted parts:
( the escape character for cmd.exe is ^ )
it's all in double quoted parts
(as seen by cmd.exe)
c.
if this will be placed in a batch file, double the % characters
\"C:\TEST" "%%&^" "A\\\" ↑
Result: To get desired parameter use this:
"\"C:\TEST ^%%^&^^ A\\\""
Another way to get the same result would be at step 2a just escape all special characters including all double quotes so there are no double quoted parts.
\^"C:\TEST^" ^"%^&^^^" ^"A\\\^" ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑
c.
and if this will be placed in a batch file, double the % characters
\^"C:\TEST^" ^"%%^&^^^" ^"A\\\^" ↑
Sample Test File:
TestParams8_10.bat
REM all 4 lines should produce the same result
ShowParams.exe "\"C:\TEST ^%%^&^^ A\\\""
ShowParams.exe ^"\^"C:\TEST %%^&^^ A\\\^"^"
ShowParams.exe "\"C:\TEST ^%%^&^^ A\\\""
ShowParams.exe \^"C:\TEST^" ^"%%^&^^^" ^"A\\\^"
8.2
How To Pass A Parameter to: a Batch File from the Command Line
To get a parameter into a batch file you need to work backwards through the two parsings it will go through:
The cmd.exe command line parser parses your command line & parameters and then starts running the batch file
The batch file retrieves the parameters, but when you use them, they get parsed again. Here's an example:
a batch file line contains %1
%1 is replaced with your parameter
that line is then sent to the command line parser for execution, where it gets parsed
Overview of steps:
Start with the parameter you want
Apply the command line parsing rules that cmd.exe will apply when you enter the command and parameters [sec. 7]
Again, apply the command line parsing rules that cmd.exe will apply when you enter the command and parameters [sec. 7]
Step Details:
The steps to create your parameter are:
Apply the Command Line Parser (cmd.exe) parsing rules
determine what cmd.exe will see as the quoted parts
escape the special characters < > | & ^ not in a double quoted part
again, escape the special characters < > | & ^ not in a double quoted part
•the escape character for cmd.exe is ^
•it may also be necessary to escape ( ) @ !
•it's OK to escape everything
If your command line will be placed in a batch file, double the % character7
The Command Line to Batch File Rules:
Combining the two steps above gives us the following rules:
Use ^^^ outside double quotes to escape < > & | ^
to insert < use ^^^<
to insert > use ^^^>
to insert | use ^^^|
to insert ^ use ^^^^
Sometimes it may be necessary to also escape ( ) @ !
It's OK to escape everything
Note ^ is also the line continuation character.
Space, Tab, Semicolon, Comma:
Note that you can't have a space within a parameter without having some double quotes around it somehow. All spaces must be within a double quoted part. Otherwise the space will act as a parameter delimiter. (Same with tabs, semicolons, commas.)
Command line arguments can be separated by an unquoted semicolon or comma. This affects builtin commands like COPY and batch file parameters.
If the command is called by name (no path), the following slash is treated a separator, as in DIR/P. This affects both builtin commands and external commands. Note: If you want to use NT-style slash-separated paths with DOS utilities you have to quote them (as in TYPE "C:/BOOT.INI").16
Example 9.1: Command Line to Batch File
Example 9.1: &<>^|()@!
Parameter
Start with the parameter you want
&<>^|()@!
1.
Apply the Command Line to Batch File parsing rules
a.
determine what cmd.exe will see as the quoted parts:
it's all unquoted
b.
escape the special characters not in double quoted parts:
^^^&^^^<^^^>^^^^^^^|()@! ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑
Result: To get desired parameter use this:
^^^&^^^<^^^>^^^^^^^|()@!
Sample Test File:
TestParams9_1.bat
ShowParams.bat ^^^&^^^<^^^>^^^^^^^|()@!
(Note: Since this is a batch file, if there were any % we would need to double them. WARNING! When executing a batch file from inside another batch file, the original batch file is terminated before the other one starts. This method of invoking a batch file from another is usually referred to as chaining.)
Example 9.2: Command Line to Batch File
Example 9.2: &<>^|()@!
Parameter
Start with the parameter you want
┌─────────┐ "&<>^|()@!"
1.
Apply the Command Line to Batch File parsing rules
a.
determine what cmd.exe will see as the quoted parts:
it's all in a double quoted part
b.
escape the special characters not in double quoted parts:
Nothing to escape because it's all in a double quoted part
(as seen by cmd.exe)
Result: To get desired parameter use this:
"&<>^|()@!"
Sample Test File:
TestParams9_2.bat
ShowParams.bat "&<>^|()@!"
(Note: Since this is a batch file, if there were any % we would need to double them. WARNING! When executing a batch file from inside another batch file, the original batch file is terminated before the other one starts. This method of invoking a batch file from another is usually referred to as chaining.)
Example 9.3: Command Line to Batch File
Example 9.3: &<>^|()@!"&<>^|()@!
Parameter
Start with the parameter you want
&<>^|()@!"&<>^|()@!
1.
Apply the Command Line to Batch File parsing rules
a.
determine what cmd.exe will see as the quoted parts:
┌─────────┐ ┌─── "&<>^|()@!"&<>^|()@!"
we have a problem in that the final " is interpreted by cmd.exe as opening a double quoted part. To avoid this, escape that last "
┌─────────┐ "&<>^|()@!"&<>^|()@!^^^" ↑↑↑
b.
escape the special characters not in double quoted parts:
An easier way to get the same result would be to escape the " within the parameter so it doesn't end the double quoted part. Then nothing else needs to be escaped since it's all in a double quoted part.
┌────────────────────┐ "&<>^|()@!\"&<>^|()@!" ↑
Another way to get the same result would be to escape all the special characters including all the " so nothing is in a double quoted part:
(Note: Since this is a batch file, if there were any % we would need to double them. WARNING! When executing a batch file from inside another batch file, the original batch file is terminated before the other one starts. This method of invoking a batch file from another is usually referred to as chaining.)
(Note: Since this is a batch file, if there were any % we would need to double them. WARNING! When executing a batch file from inside another batch file, the original batch file is terminated before the other one starts. This method of invoking a batch file from another is usually referred to as chaining.)
TestParams9_3c.bat
ShowParams.bat "&<>^|()@!\"&<>^|()@!"
(Note: Since this is a batch file, if there were any % we would need to double them. WARNING! When executing a batch file from inside another batch file, the original batch file is terminated before the other one starts. This method of invoking a batch file from another is usually referred to as chaining.)
(Note: Since this is a batch file, if there were any % we would need to double them. WARNING! When executing a batch file from inside another batch file, the original batch file is terminated before the other one starts. This method of invoking a batch file from another is usually referred to as chaining.)
(Note: Since this is a batch file, if there were any % we would need to double them. WARNING! When executing a batch file from inside another batch file, the original batch file is terminated before the other one starts. This method of invoking a batch file from another is usually referred to as chaining.)
10.
How To Pass A Parameter to: a VBScript, JScript, or WSH Script
from the Command Line
VBScript (.vbs), JScript9 (.js), and WSH (.wsh) scripts are run by program wscript.exe, which is the Microsoft® Windows® Script Host (WSH). WSH is a language-independent scripting host for Windows Script compatible scripting engines. Microsoft provides both Microsoft Visual Basic Script and JScript scripting engines with WSH. Windows Script Host executes scripts that exist outside an HTML or ASP page and that stand on their own as text files.10
When you run ShowParams.vbs you'll notice the window title says, "Window Script Host".
“If you want to get picky, the truth is that you can’t read command-line arguments using VBScript; that’s because VBScript doesn’t know anything about command-line arguments. But that’s all right; after all, VBScript doesn’t have to know anything about command-line arguments. That’s because Windows Script Host takes care of all that stuff.
“Any time you supply a command-line argument to a script that runs under Windows Script Host (that includes JScript scripts as well as VBScript scripts) those arguments are automatically stored in the Wscript.Arguments collection.”
On startup wscript.exe calls GetCommandLine() to get the command line, then calls wscript!SplitCommandLine(), which parses off the parameters. The rules for WSH command line parameter parsing are simple:
10.1 The WSH Command Line Parameter Parsing Rules:
parameters are separated by a space or tab (multiple spaces/tabs OK)
" begins and ends the double quoted part)
all characters within a double quoted part are accepted, including spaces and tabs)
The " character itself is always stripped from the parameter) (Note this means you can not pass a double quote as part of a parameter.))
10.2 The Microsoft® Windows® Script Host (WSH) Command Line Parameter Parsing Algorithm:
The following algorithm was reverse engineered by disassembling and examining wscript.exe and cscript.exe:
Algorithm:
call Kernel32.dll!GetCommandLine() to get the command line
make a copy of the command line
call wscript!SplitCommandLine() dry run to determine the number of parameters
allocate space for argv[] array
call wscript!SplitCommandLine() to parse parameters and fill in argv[] array
wscript!SplitCommandLine() builds an argv[] array of where each parameter begins, and writes a terminating NULL at the end of each parameter.
loop parse off next parameter: skip over spaces, tabs clear " flag save starting address of this parameter LOOP process this character: If space or tab if " flag set accept this space or tab as part of the parameter else write a 0 here to terminate this parameter and goto parse off next parameter Else if " toggle " flag, strip " (shift rest of line left 1 char) move to next char ENDLOOP endloop
Notes:
" flag - set if we're currently inside a double quoted part
The algorithm only looks for {space}, {tab}, and ("). All other characters are just characters.
You can't pass a double quote (") as part of a parameter because double quotes are always stripped off.
10.3 Putting it together:
When you launch a VBScript, JScript, or WSH script from the command line, your command line goes through two parsers:
First the cmd.exe command line parser parses your command & parameters, using its cmd.exe parsing rules. It builds a command line, and calls CreateProcess() passing it the command line it built.
Then the Windows Script Host retrieves that resulting command line and parses off the parameters, using its WSH parsing rules.
So to get a parameter into a VBScript, JScript, or WSH script, you need to work backwards through the two parsers it will go through:
Start with the parameter you want
Apply the WSH parsing rules that Windows Script Host will apply when parsing the command line it retrieves
Then apply the command line parsing rules that cmd.exe will apply when you enter the command and parameters
Step Details:
The steps to create your parameter are:
Apply the WSH parsing rules:
if there are any spaces or tabs within a parameter, add some " so they are enclosed in a double quoted part
┌───────────────┐
•you may enclose the entire parameter in double quotes: "Call Me Ishmael"
┌─┐ ┌─┐
•or you may enclose just the spaces in double quotes: Call" "Me" "Ishmael
┌────────┐
•or you can make a mess of it: Ca"ll Me Is"hmael
Apply the Command Line Parser (cmd.exe) parsing rules
determine what cmd.exe will see as the double quoted parts
escape the special characters < > | & ^ not in a double quoted part
•the escape character for cmd.exe is ^
•it may also be necessary to escape ( ) @ !
•it's OK to escape everything
If your command line will be placed in a batch file, double the % character11
10.4 Sample Scripts:
Sample 'Show Parameters' scripts:
VBScript:
ShowParams.vbs
If Wscript.Arguments.Count = 0 Then
Wscript.echo "No parameters found"
Else
i=0
Do until i = Wscript.Arguments.Count
Parms = Parms & "Param " & i & " = " & Wscript.Arguments(i) & " " & vbcr
i = i+1
loop
Wscript.echo parms
End If
JScript:
ShowParams.js
if (WScript.Arguments.Count() ==0) {
WScript.Echo("No parameters found");
}
else {
var objArgs = WScript.Arguments;
var parms = ""
for (i=0, n=objArgs.length; i<n; i++) {
parms += '\nParam '+i+'='+objArgs(i);
}
WScript.Echo(parms);
}
11.
How To Pass A Parameter to
a Perl script from the command line
ActivePerl12 and Strawberry Perl13 both call MSVCRT.dll!__getmainargs which follows the Microsoft C/C++ Parameter Parsing Rules. Therefore the steps are:
Start with the parameter you want
Apply the Microsoft C/C++ parsing rules that ShowParams.exe will apply when parsing the command line it retrieves [sec. 5]
Apply the command line parsing rules that cmd.exe will apply when you enter the command and parameters [sec. 7]
if ( $#ARGV < 0 ) {
print "No parameters\n";
}
else {
my $i = 0;
my $Parms = "";
while ( $i <= $#ARGV ) {
$Parms .= "Param $i = $ARGV[$i]\n";
$i ++;
}
print $Parms;
}
12.
How To Pass A Parameter to
a Python script from the command line
Python™14 is written in C and obtains its parameters via the argv[] vector.15 It thus uses the Microsoft C/C++ Parameter Parsing Rules. Therefore the steps are:
Start with the parameter you want
Apply the Microsoft C/C++ parsing rules that ShowParams.exe will apply when parsing the command line it retrieves [sec. 5]
Apply the command line parsing rules that cmd.exe will apply when you enter the command and parameters [sec. 7]
Sample 'Show Parameters' Python script for Python version 2:
ShowParams2.py
#!/usr/bin/python
# Filename: using_sys.py
import sys
print 'The command line arguments are:'
for i in sys.argv:
print i
print '\n\nThe PYTHONPATH is', sys.path, '\n'
Sample 'Show Parameters' Python script for Python version 3:
ShowParams3.py
#!/usr/bin/python
# Filename: using_sys.py
import sys
print( 'The command line arguments are:' )
for i in sys.argv:
print( i )
print( '\n\nThe PYTHONPATH is', sys.path, '\n' )
13.
How To Pass A Parameter to
a REXX script from the command line
8/24/2009 Under Construction...
How To Pass A Parameter to
a RUBY script from the command line
Ruby attempts to mimic the Microsoft C/C++ parameter parsing rules, but the current versions, 1.8.6 & 1.9.1, have a bug in them so they don't work properly.
(file Win32.c routine rb_w32_cmdvector, the memcpy statement needs to copy one more character to include the trailing NULL.)
Sample 'Show Parameters' RUBY script:
ShowParams.rb
ARGV.each do|a|
puts "Argument: #{a}"
end
15.
How To Pass A Parameter to
an AutoHotkey script from the command line
AutoHotkey is written in C++ and obtains its parameters via the __argv[] vector. Thus it uses the Microsoft C/C++ Parameter Parsing Rules. Therefore the steps are:
Start with the parameter you want
Apply the Microsoft C/C++ parsing rules that ShowParams.exe will apply when parsing the command line it retrieves [sec. 5]
Apply the command line parsing rules that cmd.exe will apply when you enter the command and parameters [sec. 7]
How Command Line Parameters Are Parsed
http://bit.ly/2qbdpax
About 0 Minutes
How Command Line Parameters Are Parsed
by
David Deley
© 2009(Updated 2014)
(Updated 2016)
How to escape the special characters in your parameters
Contents:
*nix
1. How a new process is created on *nix
On *nix, you launch a program using the execve API (or it's cousins execvp, execl, execlp, execle, and execvp). The interesting thing about these APIs is that they allow the caller to specify each of the command line arguments - the signature for execve is:
int execve(const char *filename, char *const argv [], char *const envp[]);
2. Passing Parameters to a new process on *nix
On *nix, the parameters are parsed off by whatever program creates the new process, before the new process is created.1
Hello
Goodbye
Friday
2.1 Example 1: Bash Shell
If you launch a program using the Bash shell command line, The Bash shell is responsible for turning the string provided by the user into the argv[] argument vector which is then passed to the program. For the Bash shell parameter parsing rules, the following links provide some information:
2.2 Example 2: Ubuntu Desktop Launcher Icon (GNOME→Nautilus)
In Ubuntu a desktop launcher icon can be created by right-clicking on the desktop and selecting "Create Launcher". This will generate a GNOME launch file ~/Desktop/launcher-name.desktop This is a text file you can browse (have a look at one). In this text file is a line starting with Exec= where the command and any command line parameters are.17
So what happens when you double-click on this desktop icon?
Ubuntu uses the GNOME Desktop Environment, which in turn uses the Nautilus File Manager. When you double-click on a desktop launcher icon, the Nautilus File Manager parses the Exec= command line in the ~/Desktop/launcher-name.desktop file and calls execve passing it argv[]. So to know how your command line parameters are parsed you need to look into how Nautilus parses command lines. There's some good documentation here:
2.3 Example 3: Kubuntu (KDE→Plasma)
Kubuntu is based on Ubuntu but uses the KDE Plasma Desktop instead of GNOME. So, to determine how your command line is parsed in that environment, you'll need to look into KDE application launchers. This starts to get complicated, because according to the documentation there are three: Kickoff, classic K menu, or Lancelot Launcher.18
It gets even more complicated, because it's possible to install both the KDE Plasma Desktop (kubuntu-desktop) as well as the GNOME desktop (ubuntu-desktop) on the same machine.
3. The *nix Parameter Parsing Rules
It all depends on who is processing your command line before the new process is created. On *nix, the parameters are parsed off by whatever program creates the new process.
This is all I have to say about *nix. The rest is about Windows.
Windows®
1. How a new process is created on Windows
On Windows, a new program is launched by calling the CreateProcess() API, which takes the command line as a string (the lpComandLine parameter to CreateProcess):
int CreateProcess( ..., lpComandLine, ... )
2. Passing Parameters to a new process on Windows
On Windows, the parameters are parsed off the command line after the new process is created, by the new process. It's considered the responsibility of the newly started application to call the GetCommandLine() API to retrieve the command line string and parse it (possibly using the CommandLineToArgvW() helper function).2
Hello
Goodbye
Friday
3. How does a C/C++ program on Windows get argv[]?
The C/C++ compiler which compiles the program secretly adds extra code to the executable that retrieves and parses the command line to extract the parameters before calling WinMain (or main). Thus, for a C/C++ executable on Windows, the parameter parsing rules are determined by the C/C++ compiler that compiled the program.
4. Everyone Parses Differently
You'll get different results if you pass a command line to ShowParams.exe (written in C/C++), ShowParams.vbs (VBScript), or ShowParams.bat (batch file):
Sample Code:
int main(int argc, char* argv[])
{
for (int i = 0; i < argc; ++i)
{
printf("param %d = ",i);
puts(argv[i]);
printf("\n");
}
return 0;
}
(Note: Avoid using printf when printing parameters, as the parameter may contain a % which would be interpreted by printf as a conversion specifier. The program may crash with a bizarre error, such as "runtime error R6002 - Floating point not loaded".)
I also wrote a short book on Unicode:
namespace ShowParams
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("There are {0} program arguments", args.Length);
foreach (string arg in args)
{
Console.WriteLine(arg);
}
}
}
}
echo Param1 = %1
echo Param2 = %2
echo Param3 = %3
Wscript.echo "No parameters found"
Else
i=0
Do until i = Wscript.Arguments.Count
Parms = Parms & "Param " & i & " = " & Wscript.Arguments(i) & " " & vbcr
i = i+1
loop
Wscript.echo parms
End If
param 0 = ShowParams.exe
param 1 = c:\test a" c:\test
param 2 = b"
There are 2 program arguments
c:\test a" c:\test
b"
param 1 = "c:\test a\"
param 2 = "c:\test b\"
param 0 = c:\test a\
param 1 = c:\test b\
Hello
Goodbye
Friday
The parameter parsing rules are determined by the C++ compiler that compiled ShowParams.exe
%2 = Goodbye
%3 = Friday
The parameter parsing rules are determined by cmd.exe which processes the batch file.
Wscript.Arguments(1) = Goodbye
Wscript.Arguments(2) = Friday
The parameter parsing rules are determined by WScript.exe which processes the VBScript file.
5. The C/C++ Parameter Parsing Rules
The documented program parameter parsing rules for Microsoft C/C++ compilers may be found by searching www.msdn.com for "Parsing C++ Command-Line Arguments".
Visual C++ Versions and Corresponding .dll
Redistribution of the shared C runtime component in Visual C++
5.1 Here are the documented (and undocumented) rules:
Note: The Rules Changed in 2008
They are referring to the scenario discussed in sec. 6.2 below, where first the command line parser (cmd.exe) parses your command, handling such things as the escape character ^ , the redirection characters > & < , the pipe character | , the % character which may identify environment variables that need to be expanded (e.g. %PROGRAMFILES%), etc. The rules here describe how your C/C++ executable will parse the lpCommandLine that was passed to CreateProcess() by cmd.exe or whoever calls CreateProcess().
The double quotes don't have to be around the whole parameter. A double quoted part may occur anywhere in the parameter.
If a closing " is followed immediately by another ", the 2nd " is accepted literally and added to the parameter.
5.2 The Microsoft C/C++ Parameter Parsing Rules Rephrased
These are the rules for parsing a command line passed by CreateProcess() to a program written in C/C++:
5.3 Summary of rules 5,6,7:
5.4 Examples
Command-Line
argv[1]
Comment
CallMeIshmael
CallMeIshmael
a plain parameter can contain any characters except {space} {tab} \ "
┌───────────────┐
"Call Me Ishmael"
Call Me Ishmael
spaces enclosed in a double quoted part
┌──────┐
Cal"l Me I"shmael
Call Me Ishmael
a double quoted part can be anywhere within a parameter
CallMe\"Ishmael
↑↑
CallMe"Ishmael
↑
\" → "
┌───────────────┐
"CallMe\"Ishmael"
↑↑
CallMe"Ishmael
↑
\" → " (whether or not in a double quoted part)
┌─────────────────┐
"Call Me Ishmael\\"
↑↑↑
Call Me Ishmael\
↑ ↑
\\" → \ + " (which may begin or end a double quoted part)
┌─────────────────┐
"CallMe\\\"Ishmael"
↑↑↑↑
CallMe\"Ishmael
↑↑
\\\" → \" (\\ → \) (\" → ")
a\\\b
↑↑↑
a\\\b
↑↑↑
backslashes not followed immediately by a double quotation mark are interpreted literally
"a\\\b"
↑↑↑
a\\\b
↑↑↑
whether or not the backslashes are in a double quoted part
5.5 Some Common Tasks
Command-Line
argv[1]
Comment
┌───────────────────┐
"\"Call Me Ishmael\""
↑↑ ↑↑
"Call Me Ishmael"
↑ ↑
the parameter includes double quotes
┌───────────┐
"C:\TEST A\\"
↑↑
C:\TEST A\
↑
the parameter includes a trailing slash
┌───────────────┐
"\"C:\TEST A\\\""
↑↑ ↑↑↑↑
"C:\TEST A\"
↑ ↑↑
the parameter includes double quotes and a trailing slash
5.6 The Microsoft Examples Explained
Command-Line Input
argv[1]
argv[2]
argv[3]
Comment
┌─────┐
"a b c" d e
┌─────┐
a b c
d
e
spaces enclosed in double quotes
┌─────┐ ┌──┐
"ab\"c" "\\" d
↑↑ ↑↑↑
┌────┐
ab"c
↑
┌─┐
\
↑
d
\" → "
\\" → \ + begin or end a double quoted part
↓ ┌───┐ ↓
a\\\b d"e f"g h
↑↑↑
a\\\b
↑↑↑
↓ ↓
de fg
h
backslashes not followed immediately by a double quotation mark are interpreted literally
↓ ↓ parameters are separated by spaces or tabs
┌───┐ a double quoted part can be anywhere within a parameter
the space enclosed in double quotation marks is not a delimiter
a\\\"b c d
↑↑↑↑
a\"b
↑↑
c
d
2n+1 backslashes before " → n backslashes + a literal "
┌───┐↓ ↓
a\\\\"b c" d e
↑↑↑↑↑
a\\b c
d
e
2n backslashes followed by a " produce n backslashes + start/end double quoted part.
↓ ↓ parameters are separated by spaces or tabs
┌───┐ a double quoted part can be anywhere within a parameter
the space enclosed in double quotation marks is not a delimiter
5.7 Double Double Quote Examples
(post 2008)
Command-Line Input
argv[1]
argv[2]
argv[3]
argv[4]
argv[5]
Comment
┌───────
"a b c""
↑↑
a b c"
↑
┌─────────────────┐
"""CallMeIshmael""" b c
↑↑ ↑↑
"CallMeIshmael"
↑ ↑
b
c
┌───────────────────┐
"""Call Me Ishmael"""
↑↑ ↑↑
"Call Me Ishmael"
↑ ↑
┌──┐ ┌┐
""""Call Me Ishmael"" b c
↑↑
"Call
↑
Me
Ishmael
b
c
(pre 2008)
Command-Line Input
argv[1]
argv[2]
argv[3]
Comment
┌─────┐
"a b c""
↑↑
a b c"
↑
"" while in a double quoted part → end double quoted part and accept 2nd " literally
┌┐ ┌┐
"""CallMeIshmael""" b c
↑↑ ↑↑
"CallMeIshmael"
↑ ↑
b
c
" Begin double quoted part.
"" while in a double quoted part → end double quoted part and accept 2nd " literally
┌┐ ↓ ↓ ┌┐
"""Call Me Ishmael"""
↑↑ ↑↑
"Call
↑
Me
Ishmael"
↑
Parameters are delimited by spaces or tabs.
" Begin double quoted part.
"" while in a double quoted part → end double quoted part and accept 2nd " literally
┌┐ ┌───────────────┐
""""Call Me Ishmael"" b c
↑↑ ↑↑
"Call Me Ishmael"
↑ ↑
b
c
Parameters are delimited by spaces or tabs.
" Begin double quoted part.
"" while in a double quoted part → end double quoted part and accept 2nd " literally
5.8 Triple Double Quotes
(post 2008)
How triple double quotes are parsed (post 2008)
..."""Call Me Ishmael"""...
↑↑↑ ↑↑↑↑
quote #1: Begin double quoted part──────┘├┘ ├┘├┘
quotes #2 & 3: Skip 1st " take 2nd " ────┘ │ │
│ │
quotes 4 & 5: Skip 1st " take 2nd " ──────────────────────┘ │
quote #6: End double quoted part────────────────────────────┘
>ShowParams.exe """Call Me Ishmael"""
param 1 = "Call Me Ishmael"
an alternative method is
┌───────────────┐
>ShowParams.exe \""Call Me Ishmael"\"
param 1 = "Call Me Ishmael"
or
┌───────────────────┐
>ShowParams.exe "\"Call Me Ishmael\""
param 1 = "Call Me Ishmael"
(pre 2008)
How triple double quotes were parsed (pre 2008)
..."""Call Me Ishmael"""...
↑↑↑ ↑↑↑
quote #1: Begin double quoted part──────┘││ │││
quote #2: End double quoted part─────────┘│ │││
quote #3: and accept this " literally─────┘ │││
│││
quote #4: Begin double quoted part────────────────────────┘││
quote #5: End double quoted part───────────────────────────┘│
quote #6: and accept this " literally───────────────────────┘
>ShowParams.exe """Call Me Ishmael"""
param 1 = "Call
param 2 = Me
param 3 = Ishmael"
an alternative method is
>ShowParams.exe \"Call Me Ishmael\"
param 1 = "Call
param 2 = Me
param 3 = Ishmael"
5.9 Quadruple Double Quotes
(post 2008)
How quadruple double quotes are parsed(post 2008)
...""""Call me Ishmael""""...
↑↑↑↑↑ ↑↑↑↑↑
quote #1: Begin double quoted part──────┘├┘├┘ │├┘││
quotes #2 & 3: Skip 1st " take 2nd " ────┘ │ ││ ││
quote #4: End double quoted part───────────┘ ││ ││
││ ││
quote #5: Begin double quoted part─────────────────────────┘│ ││
quotes #6 & 7: Skip 1st " take 2nd " ───────────────────────┘ ││
quote #8: End double quoted part──────────────────────────────┘│
Assuming this isn't another " ───────────────────────┘
>ShowParams.exe """"Call Me Ishmael""""
param 1 = "Call
param 2 = Me
param 3 = Ishmael"
an alternative method is
>ShowParams.exe \"Call Me Ishmael\"
param 1 = "Call
param 2 = Me
param 3 = Ishmael"
(pre 2008)
How quadruple double quotes are parsed (pre 2008)
...""""Call me Ishmael""""...
↑↑↑↑ ↑↑↑↑↑
quote #1: Begin double quoted part──────┘│││ │││││
quote #2: End double quoted part─────────┘││ │││││
quote #3: and accept this " literally─────┘│ │││││
quote #4: Begin another double quoted part─┘ │││││
│││││
quote #5: End double quoted part───────────────────────────┘││││
quote #6: and accept this " literally───────────────────────┘│││
quote #7: Begin double quoted part───────────────────────────┘││
quote #8: End double quoted part──────────────────────────────┘│
If this was a double quote we'd accept it literally──┘
>ShowParams.exe """"Call Me Ishmael""""
param 1 = "Call Me Ishmael"
Note quotes #7,#8 are not necessary. They contribute nothing.
>ShowParams.exe """"Call Me Ishmael""
param 1 = "Call Me Ishmael"
an alternative method is
>ShowParams.exe "\"Call Me Ishmael\""
param 1 = "Call Me Ishmael"
5.10 The Microsoft C/C++ Command Line Parameter Parsing Algorithm
(pre 2008)
The following algorithm was reverse engineered by disassembling a small C program compiled using Microsoft Visual C++ and examining the disassembled code.
See
msvcrtparsing.htmfor the actual diasssembled code with annotations.
note if odd number of backslashes, we ignore last backslash and begin again.
(Double quotes are necessary if there are any spaces or tabs in the parameter)
(post 2008)
See
msvcr100dparsing.htmfor the actual diasssembled code with annotations.
6. Who Calls CreateProcess?
So far we've talked about parsing the command line that got passed as the lpCommandLine parameter to CreateProcess(). But who calls CreateProcess? One possibility is you could write a small program which calls CreateProcess() passing it a command line.
6.1. ProgA.exe → CreateProcess()
A small program ProgA.exe calls CreateProcess() passing it a command line:
Hello
Goodbye
Friday
Another possibility is you could open a Command Prompt window and type in a command:
6.2 Command Prompt Window → CreateProcess()
The command prompt window is program cmd.exe (go to START → RUN, enter "cmd"). Program cmd.exe displays the command prompt window, reads your command, and parses it handling such things as redirection characters (>) & (<), the pipe character (|), the escape character (^), identifying and expanding Environment Variables (e.g. %PROGRAMFILES%), etc. Then cmd.exe calls CreateProcess(), passing it a command line.4
create a command line
Hello
Goodbye
Friday
Note here your command line is parsed twice:
7. The cmd.exe Command Prompt Parsing Rules
The command prompt window is program cmd.exe5 (go to START → RUN, enter "cmd"). The command prompt window.to insert < use ^<
to insert > use ^>
to insert | use ^|
to insert ^ use ^^
to insert " and begin a double quoted part use "
to insert " and not begin a double quoted part use ^"
Note ^ is also the line continuation character.
Inside Double Quotes:Note: The result is what gets passed as part of the lpCommandLine argument to the CreateProcess() API. The newly created process still needs to retrieve the lpCommandLine string and parse off the parameters using it's own parsing rules (e.g. if it's a C/C++ program, it will use the Microsoft C/C++ parameter parsing rules to create the argv[] vector. See Putting It Together below for more on this).
7.1 Examples:
└┴┘ ▲↑_ ↑_ ↑_ ↑_ ↑_
lpCommandLine = ShowParams.exe !"#$%&'()*+,-./0123456789:;<=>?@abcdefghijklmnopqrstuvwxyz[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
Then ^" is escaped by \ so ShowParams.exe will see it as a literal " (Microsoft C/C++ parsing rules)
The result is:
\^" → cmd.exe parses to give \" → ShowParams.exe parses to give → "
└┴┴┘ ▲
→ ^S^T^U^V^W^X^Y^Z^[^\^]^^^_^`^a^b^c^d^e^f^g^h^i^j^k^l^m^n^o^p^q^r^s^t^u^v^w^x^y^z^{^|^}^~
lpCommandLine = ShowParams.exe !"#$%&'()*+,-./0123456789:;<=>?@abcdefghijklmnopqrstuvwxyz[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
Then ^" is escaped by \ so ShowParams.exe will see it as a literal " (Microsoft C/C++ parsing rules)
\ itself is escaped by ^ just for the heck of it (it's OK to escape everything).
The result is:
^\^" → cmd.exe parses to give \" → ShowParams.exe parses to give → "
│ │
>ShowParams.exe "!#$%&'()*+,-./0123456789:;<=>?@abcdefghijklmnopqrstuvwxyz[\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
↑ ▲
lpCommandLine = ShowParams.exe "!#$%&'()*+,-./0123456789:;<=>?@abcdefghijklmnopqrstuvwxyz[\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
7.2 Environment Variables:
Parameter
Result
Comment
PROGRAMFILES
→
PROGRAMFILES
"PROGRAMFILES"
→
"PROGRAMFILES"
%PROGRAMFILES%
→
C:\Program Files
an environment variable
"%PROGRAMFILES%"
→
"C:\Program Files"
" + an environment variable + "
%XYZ%
→
%XYZ%
(if XYZ is not an environment variable)
PUTTING IT TOGETHER:
8.
A command line passed to a C/C++ program passes through two parsers:
Here are some examples:
1. ShowParams.exe Bed Bath ^& Beyond
└┘
↓
↓
2. ↓ Bed Bath & Beyond
↓
↓
↓
3. ↓ Bed Bath & Beyond
↓ ↓ ↓ ↓ ↓
↓ ↓ ↓ ↓ ↓
↓ ↓ ↓ ↓ ↓
4. argv[0] argv[1] ↓ ↓ ↓
argv[2] ↓ ↓
argv[3] ↓
argv[4]
param 0 = ShowParams.exe
param 1 = Bed
param 2 = Bath
param 3 = &
param 4 = Beyond
│ │
1. ShowParams.exe Bed \"Bath\" ^& Beyond
└┘
↓
↓
2. ↓ Bed \"Bath\" & Beyond
↓ └┘ └┘
↓
↓
3. ↓ Bed "Bath" & Beyond
↓ ↓ ↓ ↓ ↓
↓ ↓ ↓ ↓ ↓
↓ ↓ ↓ ↓ ↓
4. argv[0] argv[1] ↓ ↓ ↓
argv[2] ↓ ↓
argv[3] ↓
argv[4]
param 0 = ShowParams.exe
param 1 = Bed
param 2 = "Bath"
param 3 = &
param 4 = Beyond
1. ShowParams.exe ^"Bed Bath ^& Beyond^"
└┘ └┘ └┘
↓
↓ ┌─────────────────┐
↓ │ │
2. ↓ "Bed Bath & Beyond"
↓
↓ ↓
↓ ↓
↓
3. ↓ Bed Bath & Beyond
↓ ↓
↓ ↓
↓ ↓
4. argv[0] argv[1]
param 0 = ShowParams.exe
param 1 = Bed Bath & Beyond
1. ShowParams.exe ^"Bed \^"Bath\^" ^& Beyond^"
└┘ └┘ └┘ └┘ └┘
↓
↓ ┌─────────────────────┐
↓ │ │
2. ↓ "Bed \"Bath\" & Beyond"
↓ └┘ └┘
↓
↓ ↓
↓ ↓
↓
3. ↓ Bed "Bath" & Beyond
↓ ↓
↓ ↓
↓ ↓
4. argv[0] argv[1]
param 0 = ShowParams.exe
param 1 = Bed "Bath" & Beyond
It gets harder when double quotes are not escaped with ^ as cmd.exe will now interpert them as “Start or end a double quoted part.”
│ │
1. ShowParams.exe "Bed Bath ^& Beyond"
↓
↓ ┌──────────────────┐
↓ │ │
2. ↓ "Bed Bath ^& Beyond"
↓
↓ ↓
↓ ↓
↓
3. ↓ Bed Bath ^& Beyond
↓ ↓
↓ ↓
↓ ↓
4. argv[0] argv[1]
param 0 = ShowParams.exe
param 1 = Bed Bath ^& Beyond
1. ShowParams.exe ^"Bed Bath \^" Beyond^"
└┘ └┘ └┘
↓
↓ ┌──────────────────┐
↓ │ │
2. ↓ "Bed Bath \" Beyond"
↓
↓ ↓
↓ ↓
↓
3. ↓ Bed Bath " Beyond
↓ ↓
↓ ↓
↓ ↓
4. argv[0] argv[1]
param 0 = ShowParams.exe
param 1 = Bed Bath " Beyond
1. ShowParams.exe ^"Bed Bath \\\^" Beyond^"
└┘ └┘ └┘
↓
↓ ┌────────────────────┐
↓ │ │
2. ↓ "Bed Bath \\\" Beyond"
└┴┴┘
↓
↓ ↓
↓ ↓
↓
3. ↓ Bed Bath \" Beyond
↓ ↓
↓ ↓
↓ ↓
4. argv[0] argv[1]
param 0 = ShowParams.exe
param 1 = Bed Bath \" Beyond
The C/C++ command line parser interperts the first " as “Start a double quoted part” and the double quote is removed.
The C/C++ command line parser interperts \\\" inside the double quoted part as a literal \"
The C/C++ command line parser interperts the ending " as “End the double quoted part” and the double quote is removed.
1. ShowParams.exe ^"\^"Bed Bath Beyond\^"^"
└┘ └┘ └┘└┘
↓
↓ ┌───────────────────┐
↓ │ │
2. ↓ "\"Bed Bath Beyond\""
└┘ └┘
↓
↓ ↓
↓ ↓
↓
3. ↓ "Bed Bath Beyond"
↓ ↓
↓ ↓
↓ ↓
4. argv[0] argv[1]
param 0 = ShowParams.exe
param 1 = "Bed Bath Beyond"
cmd.exe command line parser interprets \ as an ordinary character.
cmd.exe command line parser interprets ^" as an escaped " character so it does not start or end a double quoted part. The ^ is removed. The " is not removed.
cmd.exe command line parser interprets Bed Bath Beyond\ as ordinary characters.
cmd.exe command line parser interprets ^" as an escaped " character so it does not start or end a double quoted part. The ^ is removed. The " is not removed.
cmd.exe command line parser interprets ^" as an escaped " character so it does not start or end a double quoted part. The ^ is removed. The " is not removed.
The C/C++ command line parser interperts the first " as “Start a double quoted part” and the double quote is removed.
The C/C++ command line parser interperts \" inside the double quoted part as a literal "
The C/C++ command line parser interperts \" inside the double quoted part as a literal "
The C/C++ command line parser interperts the ending " as “End the double quoted part” and the double quote is removed.
8.1
How To Pass A Parameter to:a C/C++ Program from the Command Line
A Simplified method: (2016)
The trick is to enclose parameters with ^" instead of just "
e.g. instead of:
"Bed Bath Beyond"
use
^"Bed Bath Beyond^"
The command processor cmd.exe will strip off the ^ and won't start any double quoted parts.
Simplified method steps:
i.e. replace ^ with ^^
replace < with ^<
replace > with ^>
replace | with ^|
replace & with ^&
replace ( with ^(
replace ) with ^)
replace " with ^"
Steps 3 & 4 combined are:
replace ^" with \^"
replace \^" with \\\^"
replace \\^" with \\\\\^"
replace \\\^" with \\\\\\\^"
etc.
Example 8.1: Command Line to C/C++ Program
Example 8.1: Bed Bath & Beyond
Parameter
Bed Bath & Beyond
replace < with ^<
replace > with ^>
replace | with ^|
replace & with ^&
replace ( with ^(
replace ) with ^)
replace " with ^"
Bed Bath ^& Beyond
↑
(there may be zero)
no \^" in parameter
no ^" in parameter
^"Bed Bath ^& Beyond^"
↑↑ ↑↑
no % in parameter
Result: To get desired parameter use this:
^"Bed Bath ^& Beyond^"
cmd.exe finds no double quoted parts because all " are escaped with ^
^"Bed Bath & Beyond^"
↓ ↓
"Bed Bath & Beyond"
┌─────────────────┐
"Bed Bath & Beyond"
↓ ↓
produce n backslashes + a literal "
no \" in parameter
Bed Bath & Beyond
Example 8.2: Bed "Bath" & Beyond
Parameter
Bed "Bath" & Beyond
replace < with ^<
replace > with ^>
replace | with ^|
replace & with ^&
replace ( with ^(
replace ) with ^)
replace " with ^"
Bed ^"Bath^" ^& Beyond
↑_ ↑_ ↑_
(there may be zero)
no \^" in parameter
Bed \^"Bath\^" ^& Beyond
↑__ ↑__
^"Bed \^"Bath\^" ^& Beyond^"
↑↑ ↑↑
no % in parameter
Result: To get desired parameter use this:
^"Bed \^"Bath\^" ^& Beyond^"
cmd.exe finds no double quoted parts because all " are escaped with ^
^"Bed \^"Bath\^" ^& Beyond^"
↓ ↓ ↓ ↓ ↓
"Bed \"Bath\" & Beyond"
Note that all " inside the parameter are escaped with \
┌─────────────────────┐
"Bed \"Bath\" & Beyond"
↓ ↓
produce n backslashes + a literal quotation mark.
\" becomes " (for n=0)
Bed \"Bath\" & Beyond
↓ ↓
Bed "Bath" & Beyond
Example 8.3: Bed Bath & \"Beyond"
Parameter
Bed Bath & \"Beyond"
replace < with ^<
replace > with ^>
replace | with ^|
replace & with ^&
replace ( with ^(
replace ) with ^)
replace " with ^"
Bed Bath ^& \^"Beyond^"
↑ ↑ ↑
(there may be zero)
Bed Bath ^& \\^"Beyond^"
↑
Bed Bath ^& \\\^"Beyond\^"
↑__ ↑__
^"Bed Bath ^& \\\^"Beyond\^"^"
↑↑ ↑↑
no % in parameter
Result: To get desired parameter use this:
^"Bed Bath ^& \\\^"Beyond\^"^"
cmd.exe finds no double quoted parts because all " are escaped with ^
^"Bed Bath ^& \\\^"Beyond\^"^"
↓ ↓ ↓ ↓ ↓
"Bed Bath & \\\"Beyond\""
Note that all " inside the parameter are escaped with \
┌───────────────────────┐
"Bed Bath & \\\"Beyond\""
↓ ↓
produce n backslashes + a literal quotation mark
\" becomes "
\\\" becomes \"
Bed Bath & \\\"Beyond\"
---- --
Bed Bath & \"Beyond"
Example 8.4: (Bed) <Bath> & "Beyond" | \"Kohl^s
Parameter
(Bed) <Bath> & "Beyond" | \"Kohl^s
replace < with ^<
replace > with ^>
replace | with ^|
replace & with ^&
replace ( with ^(
replace ) with ^)
replace " with ^"
^(Bed^) ^<Bath^> ^& ^"Beyond^" ^| \^"Kohl^^s
↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑
(there may be zero)
^(Bed^) ^<Bath^> ^& ^"Beyond^" ^| \\^"Kohl^^s
↑
^(Bed^) ^<Bath^> ^& \^"Beyond\^" ^| \\\^"Kohl^^s
↑ ↑ ↑
^"^(Bed^) ^<Bath^> ^& \^"Beyond\^" ^| \\\^"Kohl^^s^"
↑↑ ↑↑
no % in parameter
Result: To get desired parameter use this:
^"^(Bed^) ^<Bath^> ^& \^"Beyond\^" ^| \\\^"Kohl^^s^"
cmd.exe finds no double quoted parts because all " are escaped with ^
^"^(Bed^) ^<Bath^> ^& \^"Beyond\^" ^| \\\^"Kohl^^s^"
↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓
"(Bed) <Bath> & \"Beyond\" | \\\"Kohl^s"
Note all " inside the double quoted parameter are escaped with \
┌──────────────────────────────────────┐
"(Bed) <Bath> & \"Beyond\" | \\\"Kohl^s"
↓ ↓
produce n backslashes + a literal quotation mark
\" becomes "
\\\" becomes \"
(Bed) <Bath> & \"Beyond\" | \\\"Kohl^s
-- -- ----
(Bed) <Bath> & "Beyond" | \"Kohl^s
Example 8.5: &<>^|()@!"
Parameter
Start with the parameter you want
(parameter includes a space)
&<>^|()@!"
replace < with ^<
replace > with ^>
replace | with ^|
replace & with ^&
replace ( with ^(
replace ) with ^)
replace " with ^"
^&^<^>^^^|^(^)^@^!^"
↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑
(there may be zero)
no \^" in parameter
^&^<^>^^^|^(^)^@^!\^"
↑
^"^&^<^>^^^|^(^)^@^!\^"^"
↑↑ ↑↑
no % in parameter
Result: To get desired parameter use this:
^"^&^<^>^^^|^(^)^@^!\^"^"
cmd.exe finds no double quoted parts because all " are escaped with ^
^"^&^<^>^^^|^(^)^@^!\^"^"
↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓
"&<>^|()@!\""
Note all " inside the double quoted parameter are escaped with \
┌───────────┐
"&<>^|()@!\""
↓ ↓
produce n backslashes + a literal quotation mark
\" becomes "
&<>^|()@!\"
--
&<>^|()@!"
The following older examples show the harder way of figuring out what to use as parameters.
Example 8.6: Command Line to C/C++ Program
Example 8.6a: &<>^|()@ !
Parameter
Start with the parameter you want
(parameter includes a space)
&<>^|()@ !
literal \" with \\\"
literal \\" with \\\\\"
nothing to replace
(because there's a space in the parameter)
┌──────────┐
"&<>^|()@ !"
↑ ↑
┌──────────┐
"&<>^|()@ !"
( the escape character for cmd.exe is ^ )
Nothing to escape because it's all in a double quoted part
(as seen by cmd.exe)
no % in parameter
Result: To get desired parameter use this:
"&<>^|()@ !"
Example 8.6b: &<>^|()@ !
Parameter
Start with the parameter you want
(same as example 1a)
&<>^|()@ !
literal \" with \\\"
literal \\" with \\\\\"
nothing to replace
(A double quoted part can be anywhere within a parameter)
&<>^|()@" "!
↑ ↑
┌─┐
&<>^|()@" "!
( the escape character for cmd.exe is ^ )
┌─┐
^&^<^>^^^|^(^)^@" "^!
↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑
no % in parameter
Result: To get desired parameter use this:
^&^<^>^^^|^(^)^@" "^!
Example 8.7: Command Line to C/C++ Program
Example 8.7: &<>^|@()!"&<>^|@() !
Parameter
Start with the parameter you want
&<>^|@()!"&<>^|@()!
literal \" with \\\"
literal \\" with \\\\\"
&<>^|@()!\"&<>^|@()!
↑
"&<>^|@()!\"&<>^|@()!"
↑ ↑
┌──────────┐ ┌───
"&<>^|()@!\"&<>^|@()!"
┌──────────┐
"&<>^|()@!\"&<>^|@()!^"
↑
( the escape character for cmd.exe is ^ )
┌──────────┐
"&<>^|@()!\"^&^<^>^^^|@()!^"
↑ ↑ ↑ ↑ ↑
no % in parameter
Result: To get desired parameter use this:
"&<>^|@()!\"^&^<^>^^^|@()!^"
Another way to get the same result would be at step 1b don't enclose the parameter in double quotes, then escape all special characters including the double quote so it doesn't start a double quoted part.
^&^<^>^^^|@()!\^"^&^<^>^^^|@()!
↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑
Example 8.8: Command Line to C/C++ Program
Example 8.8a: &<>^|@() !"&<>^|@() !
Parameter
Start with the parameter you want (parameter includes leading and trailing double quotes, plus a double quote inside, and two spaces)
"&<>^|@() !"&<>^|@() !"
literal \" with \\\"
literal \\" with \\\\\"
\"&<>^|@() !\"&<>^|@() !\"
↑ ↑ ↑
┌──────────────────────────┐
"\"&<>^|@() !\"&<>^|@() !\""
↑ ↑
┌─┐ ┌───────────┐┌───
"\"&<>^|@() !\"&<>^|@() !\""
┌─┐ ┌───────────┐
"\"&<>^|@() !\"&<>^|@() !\"^"
↑
( the escape character for cmd.exe is ^ )
┌─┐ ┌───────────┐
"\"^&^<^>^^^|@() !\"&<>^|@() !\"^"
↑ ↑ ↑ ↑ ↑
no % in parameter
Result: To get desired parameter use this:
"\"^&^<^>^^^|@() !\"&<>^|@() !\"^"
Another way to get the same result would be at step 2a just escape all special characters including all double quotes so there are no double quoted parts.
^"\^"^&^<^>^^^|@() !\^"^&^<^>^^^|@() !\^"^"
↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑
Example 8.8b: &<>^|@() !"&<>^|@() !
Parameter
Start with the parameter you want (same as 3a)
"&<>^|@() !"&<>^|@() !"
literal \" with \\\"
literal \\" with \\\\\"
\"&<>^|@() !\"&<>^|@() !\"
↑ ↑ ↑
(A double quoted part can be anywhere within a parameter)
┌─┐ ┌─┐
\"&<>^|@()" "!\"&<>^|@()" "!\"
↑ ↑ ↑ ↑
┌────────┐ ┌──┐ ┌─┐ ┌───
\"&<>^|@()" "!\"&<>^|@()" "!\"
┌────────┐ ┌──┐ ┌─┐
\"&<>^|@()" "!\"&<>^|@()" "!\^"
↑
( the escape character for cmd.exe is ^ )
┌────────┐ ┌──┐ ┌─┐
\"&<>^|@()" "!\"^&^<^>^^^|@()" "!\^"
↑ ↑ ↑ ↑ ↑
no % in parameter
Result: To get desired parameter use this:
\"&<>^|@()" "!\"^&^<^>^^^|@()" "!\^"
Another way to get the same result would be at step 2a just escape all special characters including all double quotes so there are no double quoted parts.
\^"^&^<^>^^^|@()^" ^"!\^"^&^<^>^^^|@()^" ^"!\^"
↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑
Example 8.9: Command Line to C/C++ Program
Example 8.9a: "C:\TEST A\"
Parameter
Start with the parameter you want (parameter includes double quotes and a space)
"C:\TEST A\"
literal \" with \\\"
literal \\" with \\\\\"
\"C:\TEST A\\\"
↑ ↑↑
(because there's a space in the parameter)
┌───────────────┐
"\"C:\TEST A\\\""
↑ ↑
┌─┐ ┌┐
"\"C:\TEST A\\\""
( the escape character for cmd.exe is ^ )
No special characters to escape
(as seen by cmd.exe)
no % in parameter
Result: To get desired parameter use this:
"\"C:\TEST A\\\""
Another way to get the same result would be at step 2a just escape all special characters including all double quotes so there are no double quoted parts.
^"\^"C:\TEST A\\\^"^"
↑ ↑ ↑ ↑
Example 8.9b: "C:\TEST A\"
Parameter
Start with the parameter you want (same as 4a)
"C:\TEST A\"
literal \" with \\\"
literal \\" with \\\\\"
\"C:\TEST A\\\"
↑ ↑↑
(A double quoted part can be anywhere within a parameter)
\"C:\TEST" "A\\\"
↑ ↑
┌───────┐ ┌────┐ \"C:\TEST" "A\\\"
( the escape character for cmd.exe is ^ )
It's all in double quoted parts.
(as seen by cmd.exe)
no % in parameter
Result: To get desired parameter use this:
\"C:\TEST" "A\\\"
Another way to get the same result would be at step 2a just escape all special characters including all double quotes so there are no double quoted parts.
\^"C:\TEST^" ^"A\\\^"
↑ ↑ ↑ ↑
Example 8.10: Command Line to C/C++ Program
Example 8.10a: "C:\TEST %&^ A\"
Parameter
Start with the parameter you want
"C:\TEST %&^ A\"
literal \" with \\\"
literal \\" with \\\\\"
\"C:\TEST %&^ A\\\"
↑ ↑↑
┌───────────────────┐
"\"C:\TEST %&^ A\\\""
┌─┐ ┌┐
"\"C:\TEST %&^ A\\\""
( the escape character for cmd.exe is ^ )
┌─┐ ┌┐
"\"C:\TEST ^%^&^^ A\\\""
↑ ↑ ↑
┌─┐ ┌┐
"\"C:\TEST ^%%^&^^ A\\\""
↑
Result: To get desired parameter use this:
"\"C:\TEST ^%%^&^^ A\\\""
Another way to get the same result would be at step 2a just escape all special characters including all double quotes so there are no double quoted parts.
^"\^"C:\TEST %^&^^ A\\\^"^"
↑ ↑ ↑ ↑ ↑ ↑
^"\^"C:\TEST %%^&^^ A\\\^"^"
↑
Example 8.10b: "C:\TEST %&^ A\"
Parameter
Start with the parameter you want (same as 5a)
"C:\TEST %&^ A\"
literal \" with \\\"
literal \\" with \\\\\"
\"C:\TEST %&^ A\\\"
↑ ↑↑
(A double quoted part can be anywhere within a parameter)
┌─┐ ┌─┐
\"C:\TEST" "%&^" "A\\\"
↑ ↑ ↑ ↑
┌───────┐ ┌───┐ ┌────┐
\"C:\TEST" "%&^" "A\\\"
( the escape character for cmd.exe is ^ )
it's all in double quoted parts
(as seen by cmd.exe)
\"C:\TEST" "%%&^" "A\\\"
↑
Result: To get desired parameter use this:
"\"C:\TEST ^%%^&^^ A\\\""
Another way to get the same result would be at step 2a just escape all special characters including all double quotes so there are no double quoted parts.
\^"C:\TEST^" ^"%^&^^^" ^"A\\\^"
↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑
\^"C:\TEST^" ^"%%^&^^^" ^"A\\\^"
↑
Sample Test File:
ShowParams.exe "\"C:\TEST ^%%^&^^ A\\\""
ShowParams.exe ^"\^"C:\TEST %%^&^^ A\\\^"^"
ShowParams.exe "\"C:\TEST ^%%^&^^ A\\\""
ShowParams.exe \^"C:\TEST^" ^"%%^&^^^" ^"A\\\^"
8.2
How To Pass A Parameter to:a Batch File from the Command Line
To get a parameter into a batch file you need to work backwards through the two parsings it will go through:
The steps to create your parameter are:
The Command Line to Batch File Rules:
Combining the two steps above gives us the following rules:
to insert < use ^^^<
to insert > use ^^^>
to insert | use ^^^|
to insert ^ use ^^^^
Space, Tab, Semicolon, Comma:
Note that you can't have a space within a parameter without having some double quotes around it somehow. All spaces must be within a double quoted part. Otherwise the space will act as a parameter delimiter. (Same with tabs, semicolons, commas.)
Example 9.1: Command Line to Batch File
Start with the parameter you want
&<>^|()@!
it's all unquoted
^^^&^^^<^^^>^^^^^^^|()@!
↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑
Result: To get desired parameter use this:
^^^&^^^<^^^>^^^^^^^|()@!
(Note: Since this is a batch file, if there were any % we would need to double them. WARNING! When executing a batch file from inside another batch file, the original batch file is terminated before the other one starts. This method of invoking a batch file from another is usually referred to as chaining.)
Example 9.2: Command Line to Batch File
Example 9.2: &<>^|()@!
Parameter
Start with the parameter you want
┌─────────┐
"&<>^|()@!"
it's all in a double quoted part
Nothing to escape because it's all in a double quoted part
(as seen by cmd.exe)
Result: To get desired parameter use this:
"&<>^|()@!"
(Note: Since this is a batch file, if there were any % we would need to double them. WARNING! When executing a batch file from inside another batch file, the original batch file is terminated before the other one starts. This method of invoking a batch file from another is usually referred to as chaining.)
Example 9.3: Command Line to Batch File
Example 9.3: &<>^|()@!"&<>^|()@!
Parameter
Start with the parameter you want
&<>^|()@!"&<>^|()@!
┌─────────┐ ┌───
"&<>^|()@!"&<>^|()@!"
we have a problem in that the final " is interpreted by cmd.exe as opening a double quoted part. To avoid this, escape that last "
┌─────────┐
"&<>^|()@!"&<>^|()@!^^^"
↑↑↑
┌─────────┐
"&<>^|()@!"^^^&^^^<^^^>^^^^^^^|()@!^^^"
↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑
Result: To get desired parameter use this:
"&<>^|()@!"^^^&^^^<^^^>^^^^^^^|()@!^^^"
Though not necessary, it's OK to escape the rest of the characters:
┌─────────┐
"&<>^|()@!"^^^&^^^<^^^>^^^^^^^|^^^(^^^)^^^@^^^!^^^"
↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑
An easier way to get the same result would be to escape the " within the parameter so it doesn't end the double quoted part. Then nothing else needs to be escaped since it's all in a double quoted part.
┌────────────────────┐
"&<>^|()@!\"&<>^|()@!"
↑
Another way to get the same result would be to escape all the special characters including all the " so nothing is in a double quoted part:
^^^"^^^&^^^<^^^>^^^^^^^|()@!^^^"^^^&^^^<^^^>^^^^^^^|()@!^^^"
As before, though it's not necessary, it is OK to escape the rest of the characters:
^^^"^^^&^^^<^^^>^^^^^^^|^^^(^^^)^^^@^^^!^^^"^^^&^^^<^^^>^^^^^^^|^^^(^^^)^^^@^^^!^^^"
↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑ ↑↑↑
all 5 test files should produce the same result
(Note: Since this is a batch file, if there were any % we would need to double them. WARNING! When executing a batch file from inside another batch file, the original batch file is terminated before the other one starts. This method of invoking a batch file from another is usually referred to as chaining.)
(Note: Since this is a batch file, if there were any % we would need to double them. WARNING! When executing a batch file from inside another batch file, the original batch file is terminated before the other one starts. This method of invoking a batch file from another is usually referred to as chaining.)
(Note: Since this is a batch file, if there were any % we would need to double them. WARNING! When executing a batch file from inside another batch file, the original batch file is terminated before the other one starts. This method of invoking a batch file from another is usually referred to as chaining.)
(Note: Since this is a batch file, if there were any % we would need to double them. WARNING! When executing a batch file from inside another batch file, the original batch file is terminated before the other one starts. This method of invoking a batch file from another is usually referred to as chaining.)
(Note: Since this is a batch file, if there were any % we would need to double them. WARNING! When executing a batch file from inside another batch file, the original batch file is terminated before the other one starts. This method of invoking a batch file from another is usually referred to as chaining.)
10.
How To Pass A Parameter to:a VBScript, JScript, or WSH Script
from the Command Line VBScript (.vbs), JScript9 (.js), and WSH (.wsh) scripts are run by program wscript.exe, which is the Microsoft® Windows® Script Host (WSH). WSH is a language-independent scripting host for Windows Script compatible scripting engines. Microsoft provides both Microsoft Visual Basic Script and JScript scripting engines with WSH. Windows Script Host executes scripts that exist outside an HTML or ASP page and that stand on their own as text files.10 When you run ShowParams.vbs you'll notice the window title says, "Window Script Host".
“Any time you supply a command-line argument to a script that runs under Windows Script Host (that includes JScript scripts as well as VBScript scripts) those arguments are automatically stored in the Wscript.Arguments collection.”
—Hey, Scripting Guy! 2008 Winter Scripting Games: Retrieving Command-Line Arguments
http://www.microsoft.com/technet/scriptcenter/funzone/games/tips08/gtip0104.mspx
On startup wscript.exe calls GetCommandLine() to get the command line, then calls wscript!SplitCommandLine(), which parses off the parameters. The rules for WSH command line parameter parsing are simple:
10.1 The WSH Command Line Parameter Parsing Rules:
(Note this means you can not pass a double quote as part of a parameter.))
10.2 The Microsoft® Windows® Script Host (WSH) Command Line Parameter Parsing Algorithm:
The following algorithm was reverse engineered by disassembling and examining wscript.exe and cscript.exe:Algorithm:
Splitting the Command Line to get Parameters
start with: ShowParams.exe hello goodbye Friday
end with: ShowParams.exe0hello0goodbye0Friday0
↑ ↑ ↑ ↑
argv[] │ │ │ │
param 0: ───┘ │ │ │
param 1: ──────────────────┘ │ │
param 2: ────────────────────────┘ │
param 3: ────────────────────────────────┘
10.3 Putting it together:
When you launch a VBScript, JScript, or WSH script from the command line, your command line goes through two parsers:
The steps to create your parameter are:
•you may enclose the entire parameter in double quotes: "Call Me Ishmael"
•or you may enclose just the spaces in double quotes: Call" "Me" "Ishmael
•or you can make a mess of it: Ca"ll Me Is"hmael
10.4 Sample Scripts:
Sample 'Show Parameters' scripts:
VBScript:
Wscript.echo "No parameters found"
Else
i=0
Do until i = Wscript.Arguments.Count
Parms = Parms & "Param " & i & " = " & Wscript.Arguments(i) & " " & vbcr
i = i+1
loop
Wscript.echo parms
End If
WScript.Echo("No parameters found");
}
else {
var objArgs = WScript.Arguments;
var parms = ""
for (i=0, n=objArgs.length; i<n; i++) {
parms += '\nParam '+i+'='+objArgs(i);
}
WScript.Echo(parms);
}
11.
How To Pass A Parameter toa Perl script from the command line ActivePerl12 and Strawberry Perl13 both call MSVCRT.dll!__getmainargs which follows the Microsoft C/C++ Parameter Parsing Rules. Therefore the steps are:
Sample 'Show Parameters' Perl script:
print "No parameters\n";
}
else {
my $i = 0;
my $Parms = "";
while (
$Parms .= "Param $i = $ARGV[$i]\n";
$i ++;
}
print $Parms;
}
12.
How To Pass A Parameter toa Python script from the command line
Python™14 is written in C and obtains its parameters via the argv[] vector.15 It thus uses the Microsoft C/C++ Parameter Parsing Rules. Therefore the steps are:
Sample 'Show Parameters' Python script for Python version 2:
# Filename: using_sys.py
import sys
print 'The command line arguments are:'
for i in sys.argv:
print i
print '\n\nThe PYTHONPATH is', sys.path, '\n'
# Filename: using_sys.py
import sys
print( 'The command line arguments are:' )
for i in sys.argv:
print( i )
print( '\n\nThe PYTHONPATH is', sys.path, '\n' )
13.
How To Pass A Parameter toa REXX script from the command line
8/24/2009 Under Construction...
Sample 'Show Parameters' REXX script:
Param1 = %1%
Param2 = %2%
Param3 = %3%
MsgBox GetCommandLine=%string%`nNumParams = %0%`nParam1 = %1%`nParam2 = %2%`nParam3 = %3%
ExitApp
13.
How To Pass A Parameter toa RUBY script from the command line
Ruby attempts to mimic the Microsoft C/C++ parameter parsing rules, but the current versions, 1.8.6 & 1.9.1, have a bug in them so they don't work properly.
(file Win32.c routine rb_w32_cmdvector, the memcpy statement needs to copy one more character to include the trailing NULL.)
Sample 'Show Parameters' RUBY script:
puts "Argument: #{a}"
end
15.
How To Pass A Parameter toan AutoHotkey script from the command line
AutoHotkey is written in C++ and obtains its parameters via the __argv[] vector. Thus it uses the Microsoft C/C++ Parameter Parsing Rules. Therefore the steps are:
Sample 'Show Parameters' AutoHotkey script:
NumParams = %0%
Param1 = %1%
Param2 = %2%
Param3 = %3%
result := DllCall("kernel32\GetCommandLineW")
pointer := result
string := DllCall("MulDiv","int",pointer,"int",1,"int",1,"str")
MsgBox GetCommandLine=%string%`nNumParams = %0%`nParam1 = %1%`nParam2 = %2%`nParam3 = %3%
ExitApp
David Deley © 2009
http://daviddeley.com
Last update: January 1, 2016
via daviddeley.com http://daviddeley.com
June 6, 2019 at 04:39PM
The text was updated successfully, but these errors were encountered: