|
Answer» Hi, all.
I have a script file that I need to move to the users javascript folder in the version of the PDF reader that they use (Acrobat 10 vs Reader DC). On an x86 system, Acrobat is located at C:\Program Files (x86)\Adobe\Acrobat 10.0\Acrobat\Javascripts and Reader's javascript folder is found at C:\Program Files (x86)\Adobe\Acrobat Reader DC\Reader\Javascripts . Obviously I have to take into account the users system type - the folder address will not be the same.
Here is the batch file I have so far with help from the internet: Code: [Select]SET ProgFiles86Root=%ProgramFiles(x86)% IF NOT "%ProgFiles86Root%"=="" GOTO win64 SET ProgFiles86Root=%ProgramFiles% :win64
SET SCRIPT="%USERPROFILE%\Desktop\AlbLog\LCB_SaveAs.js" SET ACRO="%ProgFiles86Root%\Adobe\Acrobat 10.0\Acrobat\Javascripts"
move %SCRIPT% %ACRO%
PAUSEIt goes through but says the system cannot find the specified path EVEN though it looks good in the output. Here is a screenshot:
Is this sufficient enough to at least move the script to Acrobat10? Should I make more than one batch file, one for acrobat10 and one for reader dc, and have the user just choose one of them? Will I have anymore problems with OS type (64vs86)?
Thanks in advance.Start by re-thinking your logic here..
First, bath program defensively! Always consider all possible cases, and be prepared to detect and handle them. There's also many useful batch programming tips and tricks that will save you many headaches; I'll go over some of them here.
Second, there's two things you want to check regarding the source file: Whether the path to the file actually exists, and if so, whether the file itself exists at that path.
Third, you want to locate one (or more) existing destination paths, and possibly files.. The files so you can check that they do NOT exist, so you do not unintentionally wipe out a previously existing one.
There are some things I'm doing in this code that may not make sense, or may seem like "overkill" right now, but I do them because it makes it very easy to modify the code to do other related tasks or to rewrite it to be more generalized so you can do something similar with other software by just changing a few things.
Code: [Select]@ECHO OFF SETLOCAL ENABLEEXTENSIONS
:: Set the Source Path, File, and Full (where full is simply combining Path and File) SET "SrcPath=%UserProfile:~%\Desktop\AlbLog" SET "SrcFile=LCB_SaveAs.js" SET "SrcFull=%SrcPath%\%SrcFile%"
:: Check if the source path and file exist.. IF NOT EXIST "%SrcPath%" GOTO ErrNoSrcPath IF NOT EXIST "%SrcFull%" GOTO ErrNoSrcFile
:: If we got here, the source path/file look good, so try to find possible destinations.. SET "DstFound="
:: Set each potential Acrobat path fragment SET "Acro10=Adobe\Acrobat 10.0\Acrobat\Javascripts" SET "AcroDC=Adobe\Acrobat Reader DC\Reader\Javascripts"
:: Try each of the standard "Program Files" locations IF EXIST "%ProgramFiles%\%Acro10%" CALL :FoundDest "%ProgramFiles%\%Acro10%" IF EXIST "%ProgramFiles%\%AcroDC%" CALL :FoundDest "%ProgramFiles%\%AcroDC%" IF EXIST "%ProgramFiles(x86)%\%Acro10%" CALL :FoundDest "%ProgramFiles(x86)%\%Acro10%" IF EXIST "%ProgramFiles(x86)%\%AcroDC%" CALL :FoundDest "%ProgramFiles(x86)%\%AcroDC%"
IF "#%DstFound%#" == "##" GOTO ErrNoDstFound
:: We're done, so go to the FINAL cleanup sction GOTO :CleanUp
:: ######################################################################
:: ###################################################################### :: Sub-sections/sub-routines/etc :: ######################################################################
:: ---------------------------------------------------------------------- :: This is called each time one of the possible target destinations is found. :: As written, this code will trigger for EACH Acrobat installation found, :: and may trigger more than once if more that one found. If this is not :: desired, you'll have to figure out some other logic to use.. :DestFound SET "DstPath=%~1" SET "DstFile=%SrcFile%" SET "DstFull=%DstPath%\%DstFile%"
:: If you want to overwrite any pre-existing destination file, :: comment out the following line (put :: in front of it) IF EXIST "%DstFull" GOTO :ErrDstFileExists
:: Actually do the copy/move, at last! ECHO COPY "%SrcFull%" "%DstFull%" :: NOTE - Remove the ECHO in front of COPY once you're satisfied the code will work :: properly. While testing, it's a good idea to put an ECHO in front of "Action" commands, :: such as COPY, MOVE, DEL/ERASE, FORMAT, NUKETHEWORLD, etc.. So instead of actually :: *performing* the command, it will ECHO on screen what the command WOULD do without :: the ECHO in front. Once you're satisfied it's doing the right thing, remove it and :: hope for the best..
:: Set our %DstFound% "flag" SET "DstFound=%DstFull%"
GOTO :EOF
:: ###################################################################### :: Error Handlers :: ######################################################################
:: ---------------------------------------------------------------------- :ErrNoSrcPath ECHO *** Warning: Source path not found: "%SrcPath%" GOTO :CleanUp
:: ---------------------------------------------------------------------- :ErrNoSrcFile ECHO *** Warning: Source file not found: "%SrcFull%" GOTO :CleanUp
:: ---------------------------------------------------------------------- :ErrNoDstFound ECHO *** Warning: Unable to locate a known Acrobat installation! GOTO :CleanUp
:: ---------------------------------------------------------------------- :ErrDstFileExists ECHO *** Warning: Skipping destination "%DstFull%" because it already exists! GOTO :CleanUp
:: ###################################################################### :: Final cleanup :: ###################################################################### :CleanUp ENDLOCAL GOTO :EOF
:: ###################################################################### :: END OF BATCH FILE, GOODBYE! :: ###################################################################### :EOF
Understand that there's still a few things *I* would do differently, such as making backup copies of the source and destination files (if any), and so on. But this should work for a starting point..
There's a few things I probably need to explain, and they're good practice to learn when programming batch files, so..
First, SETLOCAL ENABLEEXTENSIONS is a *MUST* early on in any batch file. It creates a sub-environment that is a copy of the current environment, but only lasts until the batch file is done. By doing this, you can avoid clobbering important environment variables, and set up specific environments for executing other commands. (This may not be as important in todays Windows world, since many batch files are loaded in to their own dedicated CMD.EXE anyhow, without a "global environment"..) It also keeps your environment variables within your batch file from polluting the main environment when working from the console command line.
Second, I always use comments in the form of :: comment here, rather then @REM (or simply REM). This is because CMD.EXE treats any line starting with ":" as a label, making it effectively a "no operation". The second ":" is needed to purposely cause CMD.EXE to "error" out on treating it like a label, and stop further processing of the rest of the line. If I were to use @REM, CMD.EXE would still try to *process* EVERYTHING after the @REM, and error out if there were any errors, which can cause trouble or batch file execution failure if you type certain constructs within the comment text. :: comment simply avoids these pitfalls.
Third, ALWAYS use the form SET "VAR=VALUE", and NOT the form SET VAR="VALUE". This is because of the way CMD.EXE (mis)handles quotes (") within vvariables, and many programs and commands will fail or have problems with improper quoting. By using the form SET "VAR=VALUE", it pretty much avoids the issue: The variable is set without the outer quotes; They're STRIPPED off before CMD.EXE performs the SET command. You might wonder then about path/file names with spaces, and how to quote them.. Well, thats related to the next bit..
Fourth, Fifth, .. STRIP outter quotes from input and variables while working with them, and DELAY re-quoting UNTIL it's NECESSARY -- That is, once you perform some kind of ACTION on the variable, other then SET.
You may have noticed those odd variable names I used, such as %UserProfile:~% or %~1. What's with the :~ or ~? Well, when expanding a full variable name, if you put a :~ before the ending %, the variable will be replaced with the outter quotes stripped. The same with single number/character vars, such as %1 or %%I (like in FOR loops), which is just %~1 or %%~I (no : in these cases). (Also, if you look at HELP FOR and HELP SET, there's other MODIFIERS you can use to extract portions of the variable, such as path only, file name only, and so on.. Very handy!)
Anyhow, with SET "SrcPath=%UserProfile:~%\Desktop\AlbLog", if %UserProfile% contined "C:\Users\Admin" (including the quotes), SrcPath would be set to "C:\Users\Admin\Desktop\AlbLog" (without the outer quotes). If I had done SET SrcPath="%UserProfile%\Desktop\AlbLog", then SrcPath would have been ""C:\Users\Admin"\Desktop\AlbLog". See how the extra quotes would have made the path harder to parse by including them in the wrong place? So, we strip them when we SET them by using both the SET "VAR=VALUE" form, and by using ~/:~ to strip quotes from input variables.
On the other hand, when you actually USE the variable, in case the path were to contain spaces, we would usually need to re-add the outter quotes. So, when I did IF NOT EXIST "%SrcPath%" GOTO ErrNoSrcPath, you can see I enclosed the variable reference itself in quotes. This ensured that the path was enclosed in quotes in case it had any spaces in it. So when you USE a variable that you're previously stripped quotes from, simply re-add them by wrapping the variable reference in quotes. (Unless you're still using them in a SET command to build up the full path -- Wait to ADD quotes until you're sure they're NEEDED..)
The rest of the code should be straightforward to understand.. On various error conditions/tests, we jump via GOTO to an error handler, which echos a message them jumps to :CleanUp, which cleans up SETLOCAL with a matching ENDLOCAL, then jumps to :EOF. (GOTO :EOF is special in batch files, it means to exit the batch file without doing anything else.)
The CALL :FoundDest ... might be new to you; It simply means to jump to the label :FoundDest, execute the code there, until it exits the batch file, via GOTO :EOF, which is special in this case: Rather than completely exit the batch file as normal, it jumps BACK to the line where we did the CALL from, and continues executing the next line. If you program in computer programming languages, think of CALL as a subroutine/function call, or more like a GOSUB than a GOTO. In addition, when you CALL :label, and parameters after the label are passed to the CALL'd section as %1, %2, %3, and so on, just the same as if you used %1, %2, %3... in a regular batch file as parameters. These parameters temporarily over-ride the normal %# parms until after the return from the CALL.
An lastly, I used a variable as a "flag": SET "DstFound=", which sets DstFound to nothing/an empty value, making it undefined. If we never execute one of the CALL lines, we'll never execute the line that sets DstFound to the destination found. So we test it for an empty value, and if it's empty, we error out that we found no suitable destination/Reader installation.
Please feel free to ask if any of the code (or explainations so far) do not make sense (or give errors--I did not test the code, and may have missed something causing an error.. (Hey, I can't give you EVERYTHING on a silver plate.. Most of my clients pay me money to write code for them!) Amazing! Thank you so much for explaining the code and giving tips as well! Much appreciated.
Could you explain the 'CALL :label' function again, please? I'm getting an error centered around the 'CALL :FoundDest' function I think. I commented out EOF and added PAUSE at the end of the file so that I could read the error I was getting: Code: [Select]The system cannot find the batch label specified - FoundDest The system cannot find the batch label specified - FoundDest *** Warning: Unable to locate a known Acrobat installation! Press any key to continue . . . There is no :FoundDest outside of that part of the code. Should it be DestFound? (or change the called label to FoundDest)
Thanks again for your help!
*edit btw the NUKETHEWORLD command you mentioned at the end of the code does nothing!! Sorry for the double post, couldn't edit my previous.
So I changed the DestFound labelled subroutine to FoundDest and I get a syntax error: Code: [Select]C:\>test3.bat
C:\>SETLOCAL ENABLEEXTENSIONS C:\>SET "SrcPath=C:\Users\Justin.Cha\Desktop\AlbLog" C:\>SET "SrcFile=LCB_SaveAs.js" C:\>SET "SrcFull=C:\Users\Justin.Cha\Desktop\AlbLog\LCB_SaveAs.js" C:\>IF NOT EXIST "C:\Users\Justin.Cha\Desktop\AlbLog" GOTO ErrNoSrcPath C:\>IF NOT EXIST "C:\Users\Justin.Cha\Desktop\AlbLog\LCB_SaveAs.js" GOTO ErrNoSrcFile C:\>SET "DstFound=" C:\>SET "Acro10=Adobe\Acrobat 10.0\Acrobat\Javascripts" C:\>SET "AcroDC=Adobe\Acrobat Reader DC\Reader\Javascripts" C:\>IF EXIST "C:\Program Files\Adobe\Acrobat 10.0\Acrobat\Javascripts" CALL :FoundDest "C:\Program Files\Adobe\Acrobat 10.0\Acrobat\Javascripts" C:\>IF EXIST "C:\Program Files\Adobe\Acrobat Reader DC\Reader\Javascripts" CALL :FoundDest "C:\Program Files\Adobe\Acrobat Reader DC\Reader\Javascripts" C:\>IF EXIST "C:\Program Files (x86)\Adobe\Acrobat 10.0\Acrobat\Javascripts" CALL :FoundDest "C:\Program Files (x86)\Adobe\Acrobat 10.0\Acrobat\Javascripts" C:\>SET "DstPath=C:\Program Files (x86)\Adobe\Acrobat 10.0\Acrobat\Javascripts" C:\>SET "DstFile=LCB_SaveAs.js" C:\>SET "DstFull=C:\Program Files (x86)\Adobe\Acrobat 10.0\Acrobat\Javascripts\LCB_SaveAs.js" The syntax of the command is incorrect. C:\>IF EXIST "ErrDstFileExistsAnd that's where it ends.
|