Windows Command doesn't deal with quoted arguments

Found a bug in EventGhost? Report it here.

Windows Command doesn't deal with quoted arguments

Postby edemaine » Fri Dec 09, 2016 12:29 am

I find that a System/Windows Command action of
Code: Select all
"C:\Program Files\nircmd\nircmd.exe" setdefaultsounddevice "Razer ManO'War"
does not work, while a System/Start Windows Program action of
Code: Select all
"C:\Program Files\nircmd\nircmd.exe"
with arguments
Code: Select all
setdefaultsounddevice "Razer ManO'War"
does work. On the other hand, both approaches work if the argument is a single word like
Code: Select all
Razer
rather than
Code: Select all
"Razer ManO'War"
.
edemaine
 
Posts: 3
Joined: Fri Dec 09, 2016 12:25 am

Re: Windows Command doesn't deal with quoted arguments

Postby kgschlosser » Fri Dec 09, 2016 6:59 am

as far as it not working properly..
you are saying that if you specify an argument and you have the parameter for that argument wrapped in double quotes it does not work???


this is what i know. i will have to check on the double quotes thing
the double quotes are automatically added to the path/executable automatically. so when you put everything on the same line and try and quote it yourself it comes out like this when sent to the command line

""C:\Program Files\nircmd\nircmd.exe" setdefaultsounddevice "Razer ManO'War""

which windows will have no clue what to do with

i would think that you would add the double quotes to any parameter you are specifying for a commands line switch in which the parameter you are passing contains spaces and you are trying to pass it as a single "unit" otherwise the command line switch will see multiple parameters. this goes for any command line switches that are requesting the path to something and that path has a space in it
A loved one and Time, The 2 things that can never be replaced.

Family, The only thing you don't get to choose in life.
User avatar
kgschlosser
Site Admin
 
Posts: 1274
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: Windows Command doesn't deal with quoted arguments

Postby kgschlosser » Fri Dec 09, 2016 7:59 am

i see what you are saying...

this is the code from the plugin

Code: Select all
pathname = expandvars(pathname)
arguments = expandvars(arguments)
workingDir = expandvars(workingDir)
if not disableParsingPathname:
    pathname = eg.ParseString(pathname)
if not disableParsingArguments:
    arguments = eg.ParseString(arguments)
if not disableParsingAdditionalSuffix:
    additionalSuffix = eg.ParseString(additionalSuffix)
if not workingDir:
    workingDir = dirname(abspath(pathname))


the expandvars if part of the python os library (built in)
it is used to expand any environment variables that may have been passed. like %USERPROFILE% and will replace that with the actual path that is stored in windows

and after that are some of the other options in the dialog.

but the key piece is this

Code: Select all
if not workingDir:
    workingDir = dirname(abspath(pathname))


because you entered no working directory. and because the software requires one it places the same path you enter.

this is what the executable would look like after you passed it
Code: Select all
""C:\Program Files\nircmd\nircmd.exe" setdefaultsounddevice "Razer ManO'War""

i am not putting in the escape characters it will confuse things. they don't factor into it

the abspath is also apart of the os library and what it does is it check the path and because what you entered is not a path it thinks it is a file name so it places it as a file name appended to the current eventghost running path which is C:\Users\SOMEUSER\AppData\Roaming\EventGhost\

which ends up looking like this when it's done
Code: Select all
"C:\Users\SOMEUSER\AppData\Roaming\EventGhost\"C:\Program Files\nircmd\nircmd.exe" setdefaultsounddevice "Razer ManO'War""


and that gets passed to another os command called dirname
and the dirname makes an attempt to remove the file name from the entered executable

and it ends up looking like this
Code: Select all
"C:\Users\Administrator\AppData\Roaming\EventGhost\"C:\Program Files\nircmd"


so you see why it's failing??? the above will not be a correct working directory

this is the results of passing
Code: Select all
""C:\Program Files\nircmd\nircmd.exe" setdefaultsounddevice Razor"


resuts
Code: Select all
""C:\Program Files\nircmd\nircmd.exe" setdefaultsounddevice Razer"
""C:\Program Files\nircmd\nircmd.exe" setdefaultsounddevice Razer"
"C:\Users\Administrator\AppData\Roaming\EventGhost\"C:\Program Files\nircmd\nircmd.exe" setdefaultsounddevice Razer"
"C:\Users\Administrator\AppData\Roaming\EventGhost\"C:\Program Files\nircmd"


nope didn't work

and when passing
Code: Select all
"C:\Program Files\nircmd\nircmd.exe setdefaultsounddevice Razer"


results are
Code: Select all
"C:\Program Files\nircmd\nircmd.exe setdefaultsounddevice Razer"
"C:\Program Files\nircmd\nircmd.exe setdefaultsounddevice Razer"
"C:\Program Files\nircmd\nircmd.exe setdefaultsounddevice Razer"
"C:\Program Files\nircmd"


Oh check that out.. it came out correct...

that is why there is a separate field to put the arguments in.. because not all command line switches have parameters. and an executable can have an assortment of parameters and command line switches. so unless we know every executable that's made and what it expects to see as arguments and parameters. it would never work properly.

hence the field to put in the proper assortment of command line switches and parameters.

the plugin doesn't just open up an invisible command line window and pass the information into it. there is a whole lot involved

the arguments field is there. there is no need to use any quotes in the executable field or the working directoryfield. only in the arguments if you are trying to pass something with a space and you want it to actually be one parameter

and because of computer evolution. every single file is really an executable due to file association. and directory names can have a "." in them. and file names can have an extension of up to 254 characters. and spaces in the directory names as well. so there is no real way to split the true path and file name from the parameters and arguments

so it is not a bug it's by design. and I think we both now have an education on how this plugin deals with the information passed to it. LOL
A loved one and Time, The 2 things that can never be replaced.

Family, The only thing you don't get to choose in life.
User avatar
kgschlosser
Site Admin
 
Posts: 1274
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: Windows Command doesn't deal with quoted arguments

Postby edemaine » Thu Dec 29, 2016 2:43 pm

Sorry for the delay in responding. I feel like we're talking about different things... I'm talking about the System: Windows Command feature (Executes a single windows Command line statement.) which only gives an option for Command Line -- no options for arguments or working directory. Indeed, I can include quoted arguments using System: Start Application, and that is my current work-around. But I assumed that System: Windows Command is intended to handle quoted arguments in the Command Line specification; it certainly handles unquoted arguments just fine.

I didn't realize that even these built-in plugins are written in Python. Cool! I looked at plugins/System/Command.py but I don't see what is going wrong... it looks like quoted arguments will get passed directly to CMD /C...

Wow, apparently it's a "bug" with CMD. Or I don't understand Windows quoting rules.

Code: Select all
C:\>cmd /c "C:\Program Files\nircmd\nircmd.exe" setdefaultsounddevice Speakers

C:\>cmd /c "C:\Program Files\nircmd\nircmd.exe" setdefaultsounddevice "Razer ManO'War"
'C:\Program' is not recognized as an internal or external command,
operable program or batch file.

C:\Program Files\nircmd>cmd /c nircmd setdefaultsounddevice "Razer ManO'War"


Apparently cmd doesn't like quoting both the command name and an argument... Indeed, CMD /? says this:

If /C or /K is specified, then the remainder of the command line after
the switch is processed as a command line, where the following logic is
used to process quote (") characters:

1. If all of the following conditions are met, then quote characters
on the command line are preserved:

- no /S switch
- exactly two quote characters
- no special characters between the two quote characters,
where special is one of: &<>()@^|
- there are one or more whitespace characters between the
two quote characters
- the string between the two quote characters is the name
of an executable file.

2. Otherwise, old behavior is to see if the first character is
a quote character and if so, strip the leading character and
remove the last quote character on the command line, preserving
any text after the last quote character.


If I'm reading this right, the right way to pass in quotes would be to quote the entire command line, and use /s to force the old-style quote behavior (stripping the first and last double quotes). Indeed, all of these work:

Code: Select all
C:\>cmd /s/c ""C:\Program Files\nircmd\nircmd.exe" setdefaultsounddevice Speakers"

C:\>cmd /s/c ""C:\Program Files\nircmd\nircmd.exe" setdefaultsounddevice "Razer ManO'War""
'C:\Program' is not recognized as an internal or external command,
operable program or batch file.

C:\Program Files\nircmd>cmd /s/c "nircmd setdefaultsounddevice "Razer ManO'War""

C:\>cmd /s/c ""C:\Program Files\nircmd\nircmd.exe""


That last one does as it's supposed to (displays the nircmd popup) -- it just looks really weird!

Therefore I suggest the following patch:

--- Command.py.old 2016-12-29 09:39:31.494117800 -0500
+++ Command.py 2016-12-29 09:40:10.324709500 -0500
@@ -93,10 +93,10 @@
eg.folderPath.TemporaryFiles,
"EventGhost-output-%s.txt" % ttime()
)
- processInformation.lpParameters = '/C %s > %s' % (command, filename)
+ processInformation.lpParameters = '/S/C "%s" > %s' % (command, filename)
processInformation.fMask = SEE_MASK_NOCLOSEPROCESS
else:
- processInformation.lpParameters = '/C %s' % command
+ processInformation.lpParameters = '/S/C "%s"' % command
if runAsAdmin:
processInformation.lpVerb = "runas"
processInformation.nShow = 0


I just tested this, and it works perfectly, with quoted or unquoted arguments.
edemaine
 
Posts: 3
Joined: Fri Dec 09, 2016 12:25 am

Re: Windows Command doesn't deal with quoted arguments

Postby kgschlosser » Fri Dec 30, 2016 11:13 am

well make a fork on github of EventGhost. and submit a pull request. that is the best way to get things in there. My suggestion is to make the coding style be close to what already exists.

classes and functions/methods are cap first letter of each word. attribute names are lower first letter first word and cap first letter every word there after. Constants at the module level are all upper with _ between words.

pep8 for spacing

basically make it look like whoever made the original file
and try to keep the voodoo code to a minimum LOL

submitting the pull request
I don't know if this is the proper way. but i find it easy to understand and identify by the title.
title:
[PLUGIN NAME] - Bugfix - FILE NAME, summary description
description:
brief detail of problem solution
A loved one and Time, The 2 things that can never be replaced.

Family, The only thing you don't get to choose in life.
User avatar
kgschlosser
Site Admin
 
Posts: 1274
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: Windows Command doesn't deal with quoted arguments

Postby kgschlosser » Fri Dec 30, 2016 11:16 am

and there is another action "run application" which is the same as "run command" it just has a lot more options. I never used the run command.

I am sorry about my confusion on that one. I just assumed the use of the run application.

BTW the plugin name for the pull request would be "System"
A loved one and Time, The 2 things that can never be replaced.

Family, The only thing you don't get to choose in life.
User avatar
kgschlosser
Site Admin
 
Posts: 1274
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: Windows Command doesn't deal with quoted arguments

Postby edemaine » Sat Dec 31, 2016 4:21 pm

edemaine
 
Posts: 3
Joined: Fri Dec 09, 2016 12:25 am

Re: Windows Command doesn't deal with quoted arguments

Postby kgschlosser » Sun Jan 15, 2017 5:02 am

don't know if you want to add a [SOLVED] to the title of your post. your pull request has been added to the core code

:D
A loved one and Time, The 2 things that can never be replaced.

Family, The only thing you don't get to choose in life.
User avatar
kgschlosser
Site Admin
 
Posts: 1274
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA


Return to Bug Reports

Who is online

Users browsing this forum: No registered users and 2 guests