I need help. I'm trying to set up a way to set the path for the programs, and set /P looks good, but it requires that commandline extensions are enabled, and it's nowhere near a given that a Windows box will have them enabled. How would I enable extensions while the batch file is being run, and return the status to what it was when it terminates?
You are here
UPXAU
cmd /? says:
/E:ON Enable command extensions (see below)
Did you try that?
That starts a new cmd session (which doesn't work with a batch file).
Doesn't cmd /c execute a batch file?
It would establish an environment that is inherited down the line, but wouldn't show up for other instances of the cmd.exe
Would anyone be willing to make a PAF installer for me?
Isn't it just a selfextracting 7z-copressed file renamed from *.exe to *.paf.exe?
Not quite. It's not complicated or hard to do, though (but I don't know NSIS).
It's basically just changing a couple of defines, which are the names and versions. I'd do it for you, but I'm busy working out the new ones with the latest version of FFP.
I'm having problems with optional switches. If %2 (which I want to use for --compress) isn't defined (i.e. the user didn't pass the argument), it says (set was unexpected at this time
(it works if --compress is used) when I get to if %2==--compress (set compress=true)
. I could use if DEFINED
, but there are two problems: it requires that command extensions are enabled and it can only do one action if the condition is true (which is weird). I have also given up on --verbose because of the undefined variable problem.
How do I implement optional switches?
Bear in mind that the command interpreter is performing simple text replacement of your variable references before parsing the line. When comparing variables that might possibly be empty/unset, you have to include some additional text (identical on both sides!) so you don't end up with a nonsensical if ==--compress
as in your example above. Some people add an exclamation point, X or quotes, but I think parentheses are more readable:
if %2!==--compress! ... if x%2==x--compress ... if "%2"=="--compress" ... if (%2)==(--compress) ...
Since you're specifically talking about optional arguments, you might consider the SHIFT
command.
Hope this helps. -hea
:switchboard if DEFINED %2 if %2==--compress set compress=true if DEFINED %2 if %2==-c set compress=true if %1==prepare (goto prepare) if %1==-p (goto prepare) REM an additional check is made in :prepare if %1==make-patches (goto prepare) if %1==-m (goto prepare) if %1==make-no-prepare (goto makepatches) if %1==-n (goto makepatches) if %1==apply-patches (goto applypatches) if %1==-a (goto applypatches) if %1==--help (goto help) if %1==help (goto help) if %1==-h (goto help) if %1==version (goto version) if %1==--version (goto version) if %1==-v (goto version) if %1==--info (goto info) if %1==info (goto info) if %1==-i (goto info) if %1==todo (goto todo) if %1==--todo (goto todo) if %1==-t (goto todo)
works fine as long as the variable is defined. As you can see, I have multiple if statements with --.
Could you explain shift? The help from Windows (help shift) sucks.
First of all, you don't need DEFINED
(or command extensions) if you use the comparison constructs I showed in the earlier post.
SHIFT
simply performs a logical left shift on the command-line arguments, as if they were in a register. %0
becomes inaccessible, %1
becomes accessible as %0
, %2
becomes %1
, etc. So if you had the command line:
foo.bat bar baz die
it would initially be:
After a single SHIFT
:
A second SHIFT
would render:
A final SHIFT
would leave %1 through %9 empty.
For your "switchboard", you could do something like:
:: save desired function (%1) in %func% set func=%1 :: loop through remaining args, looking for options :opt_args shift if (%1)==() goto switchboard if (%1)==(--compress) set compress=true if (%1)==(--verbose) set verbose=true if (%1)==(--towers-of-hanoi) set emacs_towers=true :: etc. goto opt_args :switchboard if (%func%)==(prepare) goto prepare :: etc.
Also, all of the above code (including your full switchboard) would be much prettier if written in Javascript/JScript or even VBS.
Sorry I took so long to reply; I was on vacation. In the meantime, I hope you remembered that Google is your friend.
Hope this helps. -hea
I understand shift now.
New problem: it looks like if/else statements don't like having other if/else statements inside them. I keep getting ") was unexpected at this time." after many attempts.
if (%2)==() ( echo One argument. ) else ( shift if (%2)==() ( echo Two arguments. ) else ( echo Three or more arguments. )
I've tried many variations on this, all returning that message (%2 is empty).
Also, all of the above code (including your full switchboard) would be much prettier if written in Javascript/JScript or even VBS.
JavaScript? How would that work?
It doesn't matter, though. I know nothing of JS or VBS, and the batch language is trying my patience as it is.
In the meantime, I hope you remembered that Google is your friend.
Yes, but it's not perfect. I used it before I did anything significant with this project, and got little beyond information on DOS (and a lot has changed since DOS). The batch language is almost dead (and time is not its friend).
I don't understand the purpose of your proposed construct. The least important issue is that you're missing a right parenthesis.
The batch language is not a structured programming language, so a batch "program" of any complexity will be full of GOTO
s, not nested conditionals and structured looping constructs. So, the "correct" way to handle a variable number of arguments in batch files is with an ugly, inefficient construct like the one I posted previously, or an uglier, more efficient one chock-full of GOTO
s. If you Google for batch command shift example, you'll find several examples (including one from M$) that look almost identical. Time hasn't erased the USENET/Internet archives...
As for the structured languages JScript and VBScript, M$ has pretty useful docs on both MSDN.microsoft.com
and microsoft.com/technet
. Since you're trying to replace batch-file functionality, you'll need to review the section on Windows Scripting Host (WSH). WSH and both scripting languages (JS & VBS) come installed on Windows 2K+.
For your level of experience, I'd probably recommend the BASIC-inspired Visual Basic Script rather than the C/C++-inspired Javascript/JScript. Start here. Don't skip the Intro/Primer sections--they explain important concepts that are simple to grasp but aren't self-evident.
Google can also help you find many code examples that shorten the learning curve for any interesting features you need.
Sorry for the delay; I was on vacation again.
As always, hope this helps. -hea
I got it figured out (didn't even have to use shift )
if NOT (%4)==() goto fourargs if NOT (%3)==() goto threeargs if NOT (%2)==() goto twoargs :switchboard ... :twoargs if %2==--compress set compress=true&&set validargs=true if %2==-c set compress=true&&set validargs=true if %2==--delete-temp set delete=true&&set validargs=true if %2==-d set delete=true&&set validargs=true if %2==silent set verbose=silent&&set validargs=true if %2==debug set verbose=debug&&set validargs=true if NOT %validargs%==true ( goto help ) else ( goto switchboard ) :threeargs if %3==-c set compress=true&&set validargs=true if %3==--compress set compress=true&&set validargs=true if %3==--delete-temp set delete=true&&set validargs=true if %3==-d set delete=true&&set validargs=true if %3==silent set verbose=silent&&set validargs=true if %3==debug set verbose=debug&&set validargs=true goto twoargs :fourargs if %4==silent set verbose=silent&&set validargs=true if %4==debug set verbose=debug&&set validargs=true goto threeargs
I could set up if statements to clean it up a bit (check if compression/deletion is already on when moving to the next section), but it's not worth the effort IMO.
The batch language is not a structured programming language, so a batch "program" of any complexity will be full of GOTOs, not nested conditionals and structured looping constructs. So, the "correct" way to handle a variable number of arguments in batch files is with an ugly, inefficient construct like the one I posted previously, or an uglier, more efficient one chock-full of GOTOs.
I figured that out (albeit the hard way)
As for the structured languages JScript and VBScript
...
Some people who almost never deal with VBScript (especially the more savvy ones; myself included) have set the system not to execute those scripts for security reasons. No useful (to the creator) virus will be written in the batch language when VBScript and (directly) executable files offer so much more versatility, so it's not likely that batch files will be excluded from execution privileges.
A little less redundancy, and easier to modify for future enhancements:
:: save desired function (%1) in %func% set func=%1 set validargs= :: loop through remaining args, looking for options :opt_args shift if (%1)==() goto check_validargs if (%1)==(--compress) set compress=true && set validargs=true if (%1)==(-c) set compress=true && set validargs=true if (%1)==(--delete-temp) set delete=true && set validargs=true if (%1)==(-d) set delete=true && set validargs=true if (%1)==(silent) set verbose=silent && set validargs=true if (%1)==(debug) set verbose=debug && set validargs=true goto opt_args :check_validargs if (%validargs%)==(true) goto switchboard goto help :switchboard if (%func%)==(prepare) goto prepare :: etc.
Some people who almost never deal with VBScript (especially the more savvy ones; myself included) have set the system not to execute those scripts for security reasons. No useful (to the creator) virus will be written in the batch language when VBScript and (directly) executable files offer so much more versatility, so it's not likely that batch files will be excluded from execution privileges.
You are correct. And, most decent security apps remove or modify the file association that allows implicit execution of WSH scripts (e.g., *.vbs, *.js) with the OPEN (or double-click) command. But, most systems still have scripting enabled as long as you explicitly invoke the scripting host and pass it your script of choice:
cscript foo.vbs
So, assuming that batch files are not also disabled, you can simply have a one-line batch file, foo.bat:
@cscript //nologo foo.vbs %*
YMMV. -hea
But, most systems still have scripting enabled as long as you explicitly invoke the scripting host and pass it your script of choice
Most systems have .vbs in %pathext%. If someone doesn't want VBScripts running on their machine, they'll (usually :p) make sure WSH isn't ever executing the scripts.
How 'bout this...
That is quite a bit cleaner. However, this is even cleaner than that:
:: save the command used (%1 will be changed) if (%1)==() goto help set command=%1 ... if NOT (%2)==() shift&&goto optargs ... :optargs if %1==(--compress) set compress=true&&set validargs=true if %1==(-c) set compress=true&&set validargs=true if %1==(--delete-temp) set delete=true&&set validargs=true if %1==(-d) set delete=true&&set validargs=true if %1==silent set verbose=silent&&set validargs=true if %1==debug set verbose=debug&&set validargs=true shift if NOT (%1)==() goto optargs if NOT %validargs%==true ( goto help ) else ( goto switchboard )
Is there any way to call Java without it giving output (short of writing a program in Java)?
java /? > nul
Thanks (/? gives an error, but -? works)! Java detection will be in beta 3 now (because it will be easy to implement).
And the PS3 is awesome so :p.
Is 7zG portable as-is? And does someone know how portable xdelta is?
AFAIK xdelta is a Windows commandline app and doesn't use the registry at all nor store any files elsewhere. I've used it in the past and think it's "portable" as-is.
What's the output string that means the terminal? I'm trying to make certain actions output to nul if verbosity is set to silent and to the terminal otherwise without doing this:
if %verbose%==silent [action] > nul else [action]
That would get messy quickly. I want to do something like this:
set out=terminal ... if %1==silent set verbose=silent&&set validargs=true ... if %verbose%==silent set out=nul ... [action] > %out%
set out= > nul
clears the variable and outputs to nul and
set out=" > nul"
keeps the quotes.
Any ideas why this is happening?
Input:
java -jar "f:\PortableApps\UPXAUPortable\App\upxau\jacksum.jar" -m -O f:\PortableApps\UPXAUPortable\Data\restored.txt -a sha1 *.exe *.dll components\*.dll uninstall\helper.exe -w "f:\PortableApps\UPXAUPortable\Data\temp\new"
Output:
Jacksum: -w: No such file or directory Jacksum: f:\PortableApps\UPXAUPortable\Data\temp\new: Is a directory
f:\PortableApps\UPXAUPortable\Data\temp\new does exist!
I can use
pushd f:\PortableApps\UPXAUPortable\Data\temp\new java -jar "f:\PortableApps\UPXAUPortable\App\upxau\jacksum.jar" -m -O f:\PortableApps\UPXAUPortable\Data\restored.txt -a sha1 *.exe *.dll components\*.dll uninstall\helper.exe popd
but this is baffling.
BTW, I'm not using hard absolute paths in the script, so don't worry.
Is there a way to detect two or more arguments as related?
I can detect a type of value and store it with arguments as long as there are no spaces.
For example:
upxau apply-patches --app-version 2.0.0.12
can be used to specify a file containing the sums for that version with this little line in :optargs
if %1==--app-version shift&&set version=%1
It will shift again like normal and check for another argument.
How would I set a variable's value in this manner if it has spaces?
For example, if I wanted to override the UPX options and have it set to -2 --all-filters with something like
upxau make-patches --archive --upxopt -2 --all-filters