Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Accessing full command line or parameters WITH QUOTES

1,355 views
Skip to first unread message

Bennett

unread,
Nov 27, 2009, 7:03:01 PM11/27/09
to
I'm trying to write a script that manipulates its command line and then runs
the command line. E.g.:

myscript.vbs "C:\Full Path\Program.exe" /option"Some option" "C:\Some file"
/etc

which would then execute:

"C:\Full Path\Program.exe" /option"Some other option" "C:\Some other file"
/etc

The problem is that VBScript doesn't allow access to the full command line
like most other languages. Furthermore, the individual parameters get the
quotes stripped, so WScript.Arguments returns:

C:\Full Path\Program.exe
/optionSome other option
C:\Some file
/etc

which is completely assinine because there is no way for me to know how
rebuild the parameters with the quotes inserted properly. What idiot thought
it would be a good idea to strip all quotes INCLUDING THOSE INSIDE A
PARAMETER??!? Sorry...I'll stop ranting. I'm just flabbergasted that
someone thought it was good idea to manipulate parameters before passing them
to our scripts.

When I was writing the script on XP, I managed to cheat and grab the CmdLine
environment variable. However, I need the script to run on Win2008, and it
doesn't have the CmdLine variable, so I'm out of luck there.

So how do I get around this? How can I either (1) get access to the full
command line similar to the CmdLine environment variable, or (2) get access
to the full, properly quoted parameters?

Tom Lavedas

unread,
Nov 27, 2009, 8:12:24 PM11/27/09
to

That's a tough one. However, the WMI Win34_Processes class can return
that information ...

Set oWMISrvc = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\.\root\cimv2")

sProcName = Mid(wsh.fullname, InstrRev(wsh.fullname, "\") + 1)

Set cProcesses = oWMISrvc.ExecQuery( _
"select * from win32_process where Name = '" & sProcName & "'")

For Each oProcess in cProcesses
If Instr(lcase(oProcess.Commandline), lcase(wsh.scriptname)) > 0
Then
wsh.echo oProcess.Commandline
End If
Next

This presumes there is only one instance of that particular script
running. Otherwise, it finds the LAST one started, which should suit
your purposes, anyway. I have no idea how to do it in 64 bit mode. I
only have access to 32 bit OS equipped machines.
____________________
Tom Lavedas

Richard Mueller [MVP]

unread,
Nov 27, 2009, 8:19:04 PM11/27/09
to

"Bennett" <Ben...@discussions.microsoft.com> wrote in message
news:0AF8A657-356A-4F70...@microsoft.com...

I think your script must handle the situations. Any parameter with embedded
spaces must be enclosed in quotes. The script must recognize that any
parameter that might have embedded spaces should always be enclosed in
quotes by the script. In all cases I can think of it will not hurt. In your
example I would say the second parameter is invalid. There should be a space
between /option and "Some other option", so the script can parse it as two
parameters and make sense of it. In other words, there should never be
embedded quotes, only quotes that completely enclose the string.

The only insurmountable problem I've encountered is the inability to include
any quote characters in a parameter. For example I cannot pass the string:

GetObject("LDAP:")

to a script. However, the only time I have had the need to do this is a
script that searches for files that contain specified text strings.

Finally, another solution might be to place the parameters in a text file
and have the VBScript program read the file using the FileSystemObject. No
quotes are stripped off.

--
Richard Mueller
MVP Directory Services
Hilltop Lab - http://www.rlmueller.net
--


Csaba Gabor

unread,
Nov 27, 2009, 8:26:13 PM11/27/09
to
On Nov 28, 1:03 am, Bennett <Benn...@discussions.microsoft.com> wrote:
> I'm trying to write a script that manipulates its command line and then runs
> the command line.  E.g.:
>
> myscript.vbs "C:\Full Path\Program.exe" /option"Some option" "C:\Some file"
> /etc
>
> which would then execute:
>
> "C:\Full Path\Program.exe" /option"Some other option" "C:\Some other file"
> /etc
>
> The problem is that VBScript doesn't allow access to the full command line
> like most other languages.  Furthermore, the individual parameters get the
> quotes stripped, so WScript.Arguments returns:
>
> C:\Full Path\Program.exe
> /optionSome other option
> C:\Some file
> /etc
>
> which is completely assinine because there is no way for me to know how
> rebuild the parameters with the quotes inserted properly.  What idiot thought
> it would be a good idea to strip all quotes INCLUDING THOSE INSIDE A
> PARAMETER??!?  Sorry...I'll stop ranting.  I'm just flabbergasted that
> someone thought it was good idea to manipulate parameters before passing them
> to our scripts.

Um, I hate to get in the way of a perfectly good rant,
but that idiot, as you say, is DOS or the Cmd Window
parser, whose function, in this case, is to parse
command line arguments. Since command line
arguments might have spaces in them, or even quotes
for that matter, there must be a mechanism for
escaping them, wouldn't you say?

So the question is really, what is that escape? And the
answer is that the primary escape mechanism is double
quotes. If we take your example, that you want to pass
/option"Three little words"
as one argument to your script, where does that leave
the guy who want to pass
/option"Thee little words" and three more
as a single argument to their script?

You can get double quotes into your argument, but you
should escape them with a backslash. For example, the
following will run the php script (assuming php is
installed) that is the 2nd (and last) argument to php:
php -r "print \"Hi mom\";"

So in your example, since you need to quote the spaces,
you might do:
/option"\"Three little words\""

But wouldn't it be better to allow/require either
/option: "Three little words"
or
/option:"Three little words"

> When I was writing the script on XP, I managed to cheat and grab the CmdLine
> environment variable.  However, I need the script to run on Win2008, and it
> doesn't have the CmdLine variable, so I'm out of luck there.

I have Win XP Pro, but I've never seen this
CmdLine environment variable. Perhaps you could
elaborate, pleas. I just checked with the following
one line script and no CmdLine shows for me:
php -r "foreach ($_ENV as $key => $env) print \"$key =^> $env\n\";"
By the way, notice the ^ escaping the > within the string.

Csaba Gabor from Vienna

Tom Lavedas

unread,
Nov 27, 2009, 8:43:31 PM11/27/09
to

Wait, it finds them all. This finds the last one ...

Set oWMISrvc = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\.\root\cimv2")

sProcName = Mid(wsh.fullname, InstrRev(wsh.fullname, "\") + 1)

Set cProcesses = oWMISrvc.ExecQuery( _
"select * from win32_process where Name = '" & sProcName & "'")

For Each oProcess in cProcesses
If Instr(lcase(oProcess.Commandline), lcase(wsh.scriptname)) > 0
Then

sCmdLine = oProcess.Commandline
End If
Next
wsh.echo sCmdLine

Pegasus [MVP]

unread,
Nov 28, 2009, 6:22:44 AM11/28/09
to

"Csaba Gabor" <dan...@gmail.com> wrote in message
news:86a52646-f78e-4559...@e27g2000yqd.googlegroups.com...

Csaba Gabor from Vienna

==========

Since WMI will report the exact command line, with double quotes, it must be
the parameter processing routine of cscript/wscript that strips the double
quotes. And attempting to escape double quotes by using strings such as
/option"\"Three little words\"" will not prevent cscript/vbscript from
showing the parameters minus the double quotes. On the other hand some
executables will display the double quotes. Try this one for fun:

mem "abc


Csaba Gabor

unread,
Nov 28, 2009, 8:24:59 AM11/28/09
to
On Nov 28, 12:22 pm, "Pegasus [MVP]" <n...@microsoft.com> wrote:
> "Csaba Gabor" <dans...@gmail.com> wrote in message

Um, that's not quite true, is it? Let me give some
examples:

If my .vbs file has the code that Tom Lavedas
suggested in his second post:


> Set oWMISrvc = GetObject("winmgmts:" _
> & "{impersonationLevel=impersonate}!\\.\root\cimv2")
>

> sProcName = _


> Mid(wsh.fullname, InstrRev(wsh.fullname, "\") + 1)
>
> Set cProcesses = oWMISrvc.ExecQuery( _

> "select * from win32_process where Name = '" & _


> sProcName & "'")
>
> For Each oProcess in cProcesses

> If Instr(lcase(oProcess.Commandline), _


lcase(wsh.scriptname)) > 0 Then
> sCmdLine = oProcess.Commandline
> End If
> Next
> wsh.echo sCmdLine

then when I attempt to run it by:
myfile.vbs
the returned command line is actually:
"C:\WINDOWS\System32\WScript.exe" "C:\delme\myfile.vbs"

This is a 'reprocessed' command line, no? But still,
our real issue is the arguments. So if I try to invoke:
myfile.vbs "\"one =^> two\""
Then for that argument, I'll actually be shown:
myfile.vbs "\"one => two\""

> it must be the parameter processing routine of
> cscript/wscript that strips the double quotes.

I find your argument interesting, but not convincing.
There could be other avenues. But I do agree that
WScript is removing at least one pair of quotes

> And attempting to escape double quotes by using
> strings such as /option"\"Three little words\""  will
> not prevent cscript/vbscript from showing the
> parameters minus the double quotes.

This is a very interesting point. I fed VBScript the
following argument:
"\"one = two\""
and VBScript turned it into 3: one, =, two
and there were no more double quotes. If I removed
the spaces on either side of the double quotes then
VBScript reported only one argument (also without
double quotes). PHP, on the other hand, preserved
one pair of double quotes and treated it only as a
single argument (regardless of spaces). I think that
strongly implies VBScript is doing some post
processing on the command line argument.

In any case, my earlier recommendation of escaping the
double quotes by prefixing them with a backslash does
not work with VBScript, but it does work with PHP (as
shown with the following one line script).

php -r "$w=new COM('winmgmts:{impersonationLevel=impersonate}!\\\\.\
\root\\cimv2');$cProc=$w->ExecQuery('select * from
win32_process');foreach ($cProc as $i=>$proc) print \"$i=^>\".$proc-
>CommandLine.\"\n\";"

Pegasus [MVP]

unread,
Nov 28, 2009, 11:00:57 AM11/28/09
to

"Csaba Gabor" <dan...@gmail.com> wrote in message
news:869831bb-3bf1-4404...@r5g2000yqb.googlegroups.com...

You initially wrote "that idiot, as you say, is DOS or the Cmd Window


parser, whose function, in this case, is to parse command line arguments."

If I can find just one command that gets processed by the command parser and
that preserves at least some double quotes then your claim cannot be
correct. The command below is such an example:

mem "abc

Since mem.exe is an external command it does get processed and parsed by the
command processor. It follows that the command processor preserves at least
some double quotes. There must be another agent that strips the lot and the
finger points to cscript.exe.

Bennett

unread,
Nov 28, 2009, 10:54:01 PM11/28/09
to

"Tom Lavedas" wrote:

> .
>

Thanks, Tom. You rock. BTW, works on Win2008 64-bit, too. Wish there was
a way to just get the script's process directly instead of hoping the last is
the correct one, but for my (current) purposes I'll only be running this
script one at a time.

0 new messages