Parse arguments of reserved chars by Send To

Microsoft Windows 7 ultimate 64-bit
March 21, 2010 at 21:05:59
Specs: Windows 7
Hi there.

I've recently come across a problem that
googling can't even solve so allow me to ask
here for help... =)

I've written a batch script that scans for
malware. I wanted to add a feature allowing it
to appear in the "Send To" mouse right-click
menu, so that any file/folders can be scanned
directly from Windows Explorer (for
convenience). Although it
works most of the time, I noticed
whenever a file/folder contains reserved
characters such as & ! (delayed expansion is
on, so ! becomes reserved), the arguments
parsing fails. Let me try to
depict the situation.

So I created a shortcut to my batch script in
the "Send To" folder, where the
argument of the shortcut is:
"C:\Malware Scanner\ms.bat" /ScanObject

Note: /ScanObject is the switch through which
my script takes a folder/file for scanning.

If I send a file containing a reserved character
(e.g. C:\12!.exe), it would be parsed like this:

"C:\Malware Scanner\ms.bat" /ScanObject
C:\12.exe

instead of

"C:\Malware Scanner\ms.bat" /ScanObject
"C:\12!.exe"

Notice the ! between 12 and .exe is gone in
the former example.

The question is how can I make it parse the
argument with double quotes? i.e. "C:\12!.exe"
instead of C:\12.exe

Upon more investigation (with echo "%*"), I
found that it smartly double-quotes whenever
the object contains space (e.g. "C:\Some
Space.exe") and unquotes when there is no
space (e.g. C:\NoSpace.exe). However it is
not so smart when encountering a reserved
character.

Thanks very much for any thought or input!

mixty


See More: Parse arguments of reserved chars by Send To

Report •


#1
March 21, 2010 at 21:57:38
I would have though such issues would have been fixed in 7, and maybe they have been, but you may want to have a read of this(the section under "DROP HANDLER/ARGUMENTS"):

http://judago.webs.com/batchbugs.htm

As for the the exclamation marks you may have to start with delayed expansion disabled, set a bunch of variables and then enable delayed expansion.

http://judago.webs.com/variablecatc...


Report •

#2
March 21, 2010 at 22:11:24
Here's a quick untested example of how to
work around the ! issue.

<UNTESTED>

@echo off
setlocal disabledelayedexpansion
if "%~1"=="" (
    echo No arguments!
    pause
    endlocal
    goto :eof
)
set argc=0

:argloop
set /a argc+=1
set argv[%argc%]="%~1"
shift
if not "%~1"=="" goto argloop

setlocal EnableDelayedExpansion
for /l %%a in (1 1 %argc%) do echo !argv[%%a]!
pause
endlocal
endlocal


Report •

#3
March 22, 2010 at 00:00:23
Here's a tentative analysis, pending wiser person's inputs:
1) my tests with quotes did not remove the exclamation problem. you will have to do that internally (inside script)
f/e, test.bat a!.txt gets:
set x="%1"
echo %x%
yields: "a.txt"
-----
and:
test.bat "a!.txt"
yields same...
2) you can determine if exclm is in the fname:
set test1=%1
setlocal disabledelayedexpansion
set test2=%1
if %test1% equ %test2% (echo samenames: no exclms) else (echo diff, exclms)
3) my solution:
setlocal disabledelayedexpansion
set test=%1
set test=%test:!=^!%
setlocal enabledelayedexpansion
runfile.exe "!test!"

i intuit that there has to be a better way... waiting for the
shoe to drop!

ps: setting local disable won't erase your var.s, only endlocal does that.
@judago: crossed up again! because it takes me hours to answer a question!


Report •

Related Solutions

#4
March 22, 2010 at 00:39:03
@nbrane

It takes me hours to answer posts too, it's just I have spent the hours in the past trying to deal with the same issues.

There is no reason to add the carets because variables set before delayed expansion are unaffected, as are variables set from set /p. To avoid the same issue on expansion delayed expansion !vars! must be used.


Report •

#5
March 22, 2010 at 06:31:19
Judago: I would have though such issues would have been fixed in 7
Yeah, POWERSHELL! handles it perfectly. (As does VBS)
PS C:\> Write-Output `$args > a.ps1
PS C:\> a.ps1 asdf "asdf 1234" 'asdf qwer' "asdf&asdf=asdf)asdf"
The term 'a.ps1' is not recognized as a cmdlet, function, operable program, or
script file. Verify the term and try again.
At line:1 char:6
+ a.ps1  <<<< asdf "asdf 1234" 'asdf qwer' "asdf&asdf=asdf)asdf"
PS C:\> LOL WE LIKE LINUX, ONLY WITH LESS THOUGHT PUT IN!
The term 'LOL' is not recognized as a cmdlet, function, operable program, or sc
ript file. Verify the term and try again.
At line:1 char:4
+ LOL  <<<< WE LIKE LINUX, ONLY WITH LESS THOUGHT PUT IN!
PS C:\> .\a.ps1 asdf "asdf 1234" 'asdf qwer' "asdf&asdf=asdf)asdf"
asdf
asdf 1234
asdf qwer
asdf&asdf=asdf)asdf
PS C:\>


Report •

#6
March 22, 2010 at 07:00:07
Razor2.3: Yeah, POWERSHELL! handles it perfectly.

My sarcasm detector is failing me, but I suspect you have fallen madly in love with POWERSHELL! ;)

Anyway what I was refering wasn't arguments as such, but the inadequate preprocessing the drop handler performed(i.e it wouldn't double quote a file named "asdf&asdf=asdf)asdf").

./ or .\ Drives me crazy too(been using bash a lot).....


Report •

#7
March 22, 2010 at 08:26:10
the inadequate preprocessing the drop handler performed
Yeah, Explorer will quote paths with spaces, as parsing command line arguments requires it, but that's it. Everything else is because CMD is unable to distinguish between text in variables, and text.

You could probably write a VBS or PS! script to do the preprocessing for you.

My sarcasm detector is failing me, but I suspect you have fallen madly in love with POWERSHELL! ;)
Everything I say is sarcasm. Or just me being a jerk. A sarcastic jerk, probably.


Report •

#8
March 22, 2010 at 09:13:56
No question that it's a CMD issue, I wouldn't bother trying to work around it, better off using another language altogether.

Report •

#9
March 23, 2010 at 11:09:03
Oh my god. I've always received great help here. So grateful.
Thanks so much!

I will use VBS to solve this. (But I always avoid VBS when I
can as I need to use my scripts under Windows PE where
VBS may not be available).

I didn't know you can do "disabledelayedexpansion" (as well
as "enable..."). If I knew that I would've written some of my
scripts more easily...

(A special thanks to Judago for putting up the tutorials btw. I
remember reading one of them before and learned a lot from
it.)


Report •

#10
March 24, 2010 at 04:58:51
I solved it with this:

'this VBscript wraps each arguments with double 
quotes,
'e.g. "arg1" "arg 2" "-arg 3" "-arg!4" "-arg&5"...
'it doesn't support named argument i.e. / 
'for switches, begin with - instead of /

Dim argsNamed, argsUnnamed, oShell, counter
Dim argAll, arg, regEx, argAllReplaced
Set argsNamed = WScript.Arguments.Named
Set argsUnnamed = WScript.Arguments.Unnamed
Set oShell = WScript.CreateObject("WScript.shell")

'loads all unnamed arguments by count property of 
wscript.arguments.unnamed
For counter = 0 To argsUnnamed.Count-1
	argAll = argAll & " " & chr(34) & argsUnnamed(counter) 
& chr(34)
Next

'remove the first space " " using regEx.Replace for pattern "."
Set regEx = New RegExp
regEx.Pattern = "."
regEx.IgnoreCase = True
argAllReplaced = regEx.Replace(argAll,"")

'in this demo, echo out everything by vbscript-style echo, then 
cmd-style echo
'adjust this according to needs.
WScript.Echo(argAllReplaced)
oShell.run "%comspec% /K echo " & argAllReplaced

(pardon me as I'm not good with vbs)

Thanks again!


Report •


Ask Question