While working on my previous question, I ran into a similar problem that I was solving initially.
In fact, I spent this month trying to create one universal .bat helper library that will handle drag-and-drop files with any names as possible. I want to make this transparent to the caller and backward compatible with any existing scripts, so the file names are passed as% 1,% 2, and I have no problem with this.
@MCND's solution is to read %CMDCMDLINE% and then a complex analysis. Therefore, I can simply write as set "a=%CMDCMDLINE:"=?%" - and have a full line in variable A, but all the quotes inside are instantly replaced by question marks ? set "a=%CMDCMDLINE:"=?%" in an incorrect line, which I can easily process further .
But it only works for .bat drag-and-drop, since I cannot read the parameters passed from the command line. I have to use %* .
My current question is: how to read it if the parameters can also contain quotation symbols, even unpaired?
Consider the following BAT file: (allows you to call "C: \ test.bat")
@echo off echo START setlocal enabledelayedexpansion set a=%1 echo a=[!a!] set b="%1" echo b=[!b!] set "c=%1" echo c=[!c!] set d=%~1 echo d=[!d!] set e="%~1" echo e=[!e!] set "f=%~1" echo f=[!f!] set g=%* echo g=[!g!] set h="%*" echo h=[!h!] set "i=%*" echo i=[!i!] endlocal echo DONE exit /b
Basically, this is all I can imagine to read the incoming packet ("call") percent parameters: forms %1 , %~1 , %* in an unquoted set x=y , quoted by set "x=y" and explicitly quoted set x="y" variations. Deferred extension is just a safe echo value (I don’t care about the ratings here ! In the parameter for simplicity).
My ultimate goal is to create a script that will never cause an error: therefore, all possible errors should appear either before my code receives execution (in the CMD hint itself) or after its completion (when the calling user tries to access the file with the broken name).
So, in this example, there should ideally be no errors between START and DONE, but they will appear in the “given” instructions before the corresponding “echo”.
Attempt # 1
Command: test
Output:
START a=[] b=[""] c=[] d=[] e=[""] f=[] g=[] h=[""] i=[] DONE
Good, not errors with null arguments. Let's get:
Attempt # 2
Command: test 123 "56"
Output:
START a=[123] b=["123"] c=[123] d=[123] e=["123"] f=[123] g=[123 "56"] h=["123 "56""] i=[123 "56"] DONE
It seems that for "normal" strings, any method works without errors.
Attempt # 3
Command: test ^&-
Output:
START '-' is not recognized as an internal or external command, operable program or batch file. a=[] b=["&-"] c=[&-] '-' is not recognized as an internal or external command, operable program or batch file. d=[] e=["&-"] f=[&-] '-' is not recognized as an internal or external command, operable program or batch file. g=[] h=["&-"] i=[&-] DONE
As you can see, cases A, D and G failed ( =%1 , =%~1 and =%* ).
Attempt # 4
Command: test "&-"
Output:
START a=["&-"] '-""' is not recognized as an internal or external command, operable program or batch file. b=[""] '-""' is not recognized as an internal or external command, operable program or batch file. c=[] '-""' is not recognized as an internal or external command, operable program or batch file. d=[] e=["&-"] f=[&-] g=["&-"] '-""' is not recognized as an internal or external command, operable program or batch file. h=[""] '-""' is not recognized as an internal or external command, operable program or batch file. i=[] DONE
Now, cases B, C, D, H and I fail ( ="%1" , "=%1" , =%~1 , ="%*" and "=%*" ).
Attempt # 5
Command: test ""^&-"
Output:
START '-"' is not recognized as an internal or external command, operable program or batch file. a=[""] b=["""&-""] c=[""&-"] d=["&-] '-"' is not recognized as an internal or external command, operable program or batch file. e=[""] '-"' is not recognized as an internal or external command, operable program or batch file. f=[] '-"' is not recognized as an internal or external command, operable program or batch file. g=[""] h=["""&-""] i=[""&-"] DONE
The remaining two cases E and F ( ="%~1" and "=%~1" ) failed to complete together with A and G ( =%1 and %* ).
Thus, none of the “installed” options will work reliably in all attempts to break my code!
Did I skip some other approach for reading the current parameters that come from an untrusted source?
Is it possible to get %… in the normal variable %…% ? Is it possible to replace the quotation marks " directly in %… ? Can I put %* in some special context where things like ampersand and & may not cause changes in execution? Is there any other way to get the arguments (call CMD again, using temporary files - anything?)
Im fine, even if it destroys the original string in these cases (unpaired quotes, unshielded special effects, etc.), but I need to get rid of the parsing error (causing uncontrolled code execution)!