Problem statement: Dragging a folder onto a batch file changes the result of a for loop while simply clicking on the batch file results in different but desired output from the mentioned for loop.
Background:
I would like to retrieve the latest created .jar file's name in a folder. A .bat file will be located in this folder where the .jars are. With the example .bat file code provided below, I double click the .bat file and get the result that I am looking for e.g. : {jar_root_dir_path}+"logger-20191030.jar", see the "Desired output:" section below for clarification.
Thing is that this .bat file will only be used in the case where someone would drag a folder onto it and then pass this information to the .jar file. This is where my problem comes in. When I drag a folder onto the batch file, I do not get any file results for the latest .jar file. Refer to the "Current output:" section below to see the output of the problem.
Code:
#Example code
#echo off
for /f "delims=" %%x in ('dir /od /b logger*.jar') do set latestjar=%%x
echo "%~dp0%latestjar%" + "%~dp0output.txt"
pause
Output:
Note: {example_path_here} in this question only acts as a placeholder for actual directory / file paths e.g. {example_dir} = "D:\Installation\Logger\"
Current output:
File Not Found
{root_directory_of_.bat} + {root_directory_of_.bat_with_output_file_name_appended}
Press any key to continue . . .
Desired output:
{root_directory_of_.bat_with_latest_.jar_file_appended} + {root_directory_of_.bat_with_output_file_name_appended}
Press any key to continue . . .
When you "drag something" to the batch file (I assume you mean drag onto the icon of the batch file or the batch file's name in Explorer), it is executed in another working folder (There probably are no .jar files in %windir%\system32).
Solution:
make sure, the working folder is what it should be. If it should be the same folder where your batch file resides, change the working folder with:
cd /d "%~dp0"
After analysis the following was determined:
A double click event will let the execution take place in the current folder where the .bat is located.
A folder drag and drop event caused execution to take place where the drag and dropped folder's parent directory is situated.
Point 2 is where the problem came in. To rectify this we "cd" back to the directory of the .bat file in order complete our original code.
Here is an example of the rectified example code of the question:
#echo off
cd /d %~dp0
for /f "delims=" %%x in ('dir /od /b logger*.jar') do set latestjar=%%x
echo "%~dp0%latestjar%" + "%~dp0output.txt"
pause
Here is the end-result of what I tried to achieve:
#echo off
cd /d %~dp0
for /f "delims=" %%x in ('dir /od /b logger*.jar') do set latestjar=%%x
java -jar "%~dp0%latestjar%" %1 > "%~dp0output.txt"
Explanation of last code segment / end-result:
- A folder is dropped onto a batch file in the file explorer -
1. The code resets back to the .bat file directory
2. We iterate through similarly named .jar files in the directory and find the most recently created one.
3. We run the latest .jar file, with an argument which is the path of the drag and dropped folder and then we output the .jar's output to an output.txt file located in the same folder as the batch file.
I've created a cmd file which uses the Robocopy command to update some files on the PC, but I can't replace the cmd files, because this contains the Robocopy script which is doing the updating. How do you replace a file which is doing the replacing?
I've moved the cmd file to another directory, which allows me to update most of the files, but I still can't replace the cmd file.
The Flags I'm using in Robocopy are /MIR /Copy:DAT /DCOPY:T
The Robocopy stopped at the cmd file and I can't replace it.
I don't see any reason for %SystemRoot%\System32\robocopy.exe failing to copy the batch file currently processed by cmd.exe than this batch file is additionally opened in an application like a text editor which prevents write access and deletion of the file as long as it is opened in the application.
However, the following code added to your batch file with unknown content could solve the problem.
#echo off
if /I not "%~dp0" == "%TEMP%\" (
copy /Y "%~f0" "%TEMP%" >nul 2>&1
if exist "%TEMP%\%~nx0" (
set "CurrentDirectory=%CD%"
set "InitialExecution=%~dp0"
cd /D "%TEMP%"
"%TEMP%\%~nx0" %*
)
)
rem Insert here other commands to execute by the batch
rem file now running from directory of temporary files.
rem The next three commands are only for demonstration.
if defined CurrentDirectory echo Initial current directory: %CurrentDirectory%
if defined InitialExecution echo Initial execution path: %InitialExecution%
pause
set "InitialExecution="
if defined CurrentDirectory set "CurrentDirectory=" & cd /D "%CurrentDirectory%" 2>nul & (goto) 2>nul & del "%~f0"
This batch file first checks if it is started from directory for temporary files. This is not the case on double clicking on the batch file, except the batch file is stored by chance in directory for temporary files by the user and double clicked on it in this directory. If batch file is not stored in directory for temporary files, it does following:
The batch file copies itself to directory of temporary files (only read access).
It verifies if the file copy was really successful which should be always true.
It defines two environment variables with path of current directory and initial execution path for later usage.
It sets the current directory to directory for temporary files.
This makes it possible to even delete the directory containing batch file on batch file directory being also current directory as typical on double clicking on a batch file stored on a local drive executed by current user.
The batch file runs itself from within directory for temporary files with passing all arguments passed to the batch file on initial execution further on its copy.
The Windows command processor cmd.exe executing the batch file continues batch file processing on its copy in temporary files directory with first line #echo off returning never to the initial batch file as started by the user.
Now with batch file processing done on a copy of initial batch file in temporary files directory and with current directory being also the directory for temporary files, the other commands in batch file can do everything in initial current directory respectively initial execution directory of the batch file like updating the files in these directories or even deleting these directories temporarily or permanently.
The three comment lines with command rem and the next three lines just demonstrate what can be done here and how to use the environment variables set by the batch file on initial execution. The two environment variables do not exist (most likely) on batch file being initially stored in directory for temporary files and executed by the user from this directory.
The batch file deletes the environment variable InitialExecution independent on its existence to restore initial environment in case of batch file executed from within a command prompt window.
Finally with batch file initially not executed from temporary files directory it deletes also the environment variable CurrentDirectory, changes the current directory back to initial current directory, if that directory still exists, and deletes itself from directory for temporary files.
(goto) 2>nul & del "%~f0" for batch file deletion without any error message output by Windows command processor was copied by me from Dave Benham's answer on How to make a batch file delete itself?
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
call /? ... explains %~dp0, %~f0 and %~nx0
cd /?
copy /?
del /?
echo /?
goto /?
if /?
pause /?
set /?
See also the Microsoft article about Using command redirection operators.
Is there a way to maintain the original file association when running a program from a batch file?
I created a batch file that calls a Windows program and performs some file maintenance. I changed the file association to the batch file. When I click on a file that's associated with that program, the batch file executes and opens the program but the file I click on isn't loaded. The original file association is lost.
This sorta makes sense because the CALL command within the batch file is once removed from the initial mouse-click that initiated the batch file.
Is there a syntax I can add that would pass the target file name to the batch file as a variable and append it to the CALL command line?
BTW, this is for an XP machine. Any assistance would be appreciated!
EDIT: here's the code I'm trying to write:
call "C:\Program Files\CorelDRAW X4\Programs\CorelDRW.exe"
:loop
if exist "C:\Documents and Settings\<user>\My Documents\corel user files\*.cdr" copy "C:\Documents and Settings\<user>\My Documents\corel user files\*.cdr" "C:\Documents and Settings\<user>\My Documents\corel user files\*.sav"
ping localhost -n 300 > nul
goto loop
I'm trying to protect CorelDraw's auto-save file. There's a bug whereby CorelDraw sometimes deletes the auto-save file during abnormal shut-down. I changed the .cdr file association so that clicking on a cdr file calls the batch file, which in turn calls Coreldraw and copies the auto-save file to a different filename. That part works, but I have to manually open the file I clicked on.
Ideally, I'd like to figure out a way to terminate the loop when I close CorelDraw, but I'll cross that bridge once I solve the file association problem.
EDIT2: Here is the result of echo %CMDCMDLINE%:
C:\WINDOWS\system32\cmd.exe /c ""C:\Documents and Settings\<user>\My Documents\corel user files\protect_autosave.bat" "C:\Documents and Settings\<user>\My Documents\filename.cdr""
As far as I have understood the requirements for the task the code to use in batch file %ProgramFiles%\CorelDRAW X4\Programs\CorelFile.bat is:
#echo off
if "%~1" == "" goto :EOF
"%ProgramFiles%\CorelDRAW X4\Programs\CorelDRW.exe" %*
for %%I in (%*) do if exist %%I copy /Y "%%~I" "%%~dpnI.sav" >nul
This batch file must be associated with file extension .cdr for example by importing following registry file on Windows XP and later Windows versions with administrator privileges:
REGEDIT4
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\.cdr]
#="CorelDrawFile"
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CorelDrawFile]
#="Corel Draw Image"
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CorelDrawFile\DefaultIcon]
#=hex(2):22,25,50,72,6f,67,72,61,6d,46,69,6c,65,73,25,5c,43,6f,72,65,6c,44,52,\
41,57,20,58,34,5c,50,72,6f,67,72,61,6d,73,5c,43,6f,72,65,6c,44,52,57,2e,65,\
78,65,22,2c,30,00
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CorelDrawFile\shell\open\command]
#=hex(2):22,25,50,72,6f,67,72,61,6d,46,69,6c,65,73,25,5c,43,6f,72,65,6c,44,52,\
41,57,20,58,34,5c,50,72,6f,67,72,61,6d,73,5c,43,6f,72,65,6c,46,69,6c,65,2e,\
62,61,74,22,20,22,25,31,22,00
It is also possible to register file extension .cdr with absolute paths with REG_SZ instead of using REG_EXPAND_SZ and %ProgramFiles% in paths.
REGEDIT4
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\.cdr]
#="CorelDrawFile"
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CorelDrawFile]
#="Corel Draw Image"
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CorelDrawFile\DefaultIcon]
#="\"C:\\Program Files\\CorelDRAW X4\\Programs\\CorelDRW.exe\",0"
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CorelDrawFile\shell\open\command]
#="\"C:\\Program Files\\CorelDRAW X4\\Programs\\CorelFile.bat\" \"%1\""
Windows Explorer calls for each selected *.cdr file the batch file on using context menu Open respectively on double clicking a single *.cdr file.
The batch file starts Corel Draw with all the arguments passed to the batch file passing to Corel Draw. This is usually just the file name of the *.cdr file with full path and file extension enclosed in double quotes.
After Corel Draw terminated, the batch file checks for existence of each file specified as command line argument and copies the file with same name in same directory with different file extension .sav.
The batch file is designed for being started with multiple *.cdr file names specified as arguments on command line. I don't know if Corel Draw supports multiple *.cdr files being specified on command line.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
call /? ... explains %* (batch file) and %1 (Windows registry).
copy /?
echo /?
for /?
if /?
I have a batch file in an administrative partition of my portable drive, with a shortcut symlinked to it on the root of the drive. The purpose of the file is to unmount the drive and remount it as the specified letter (mostly for convenience).
When the file is opened, it is opened relative to the current letter rather than to the volume ID, so naturally, when the unmount happens, the command processor has no idea what to do next as it reads the file as needed rather than caching it.
There are two foreseeable solutions that I can think of but can't figure out:
Make the file get cached into RAM before executing
Make the file run relative to the volume ID instead of the mountpoint (tried using {VOLID}\file where {VOLID} is the volume ID, but it couldn't find the file although it was there (navigating to {VOLID}\ correctly opened the directory, but trying to open the file didn't correctly open the file.
Despite of the other answers, it's trivial to cache a whole batch script to RAM.
You only need to build a single block, as blocks are parsed and cached before they can be executed.
But blocks have some drawbacks, percent expansion doesn't work, therefore you need to use delayed expansion.
call and goto can't be used, as they would try to read from the file again.
(goto) 2>nul & (
echo The script is started
REM Need to change the directory, else the unmount doesn't work
c:
mountvol e: /p
mountvol g: \\?\Volume{VOLID}\
dir G:\
echo The script will end now
REM Here you need the goto 2>nul hack to avoid an error message
)
The (goto) 2>nul & seems strange here, but it's explained at SO:How to make a batch file delete itself?.
It works also without the goto, but then the scripts ends with an error message
Have the batch file determine where it is running from see this. If it's running from the portable drive have it make a copy of itself to a permanent drive location (c:\temp for instance) then run that copy of the batch file.
When running a bath file there is no concept of running it from RAM. Windows command processor will always go back to the .bat file for the 'next' command to run. If you edit a batch file while it's running the command processor will pick up your changes.
JJF wrote already the correct answer. It is not possible to copy a batch file to RAM and inform Windows command interpreter to interpret the command lines in memory. It would be possible to create a RAM disk, copy the batch file to the RAM disk and run it from there. But this just makes the task more complicated than necessary.
This commented batch code demonstrates how to copy a batch file to directory for temporary files and start it there for complete processing in a separate Windows command process.
#echo off
rem Is the batch file path not the path of directory for temporary files?
if /I not "%~dp0" == "%TEMP%\" (
rem Copy the batch file to directory for temporary files.
copy "%~f0" "%TEMP%" >nul
rem Run the copy in a separate command process with name of the batch
rem file with extension as window title and exit this batch process.
start "%~nx0" "%TEMP%\%~nx0"
goto :EOF
)
echo The batch file is now running from directory for temporary files.
echo.
pause
rem Delete the batch file in directory for temporary files
rem and exit the command process started for this batch file.
del "%TEMP%\%~nx0" & exit
Replace the two echo commands and the pause command by your batch code.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
call /? ... explains %~dp0 (drive and path of argument 0 which is the batch file itself) and %~nx0 (name and extension of batch file)
copy /?
del /?
echo /?
exit /?
goto /?
if /?
pause /?
rem /?
start /?
See also answer on Single line with multiple commands using Windows batch file for an explanation of operator & used here two run the two commands del and exit read from one line to avoid an opened console window with an error message as batch file deleted unexpected for the Windows command interpreter while processing it.
I was using Winrar 3 to create self extractors and was using -sp flag to pass the arguments to the executable bundled inside. It was working fine.
After I updated WinRar to 5.1, it stopped working. -sp<> flag is no longer working for me.
Does anyone else face a similar issue?
Are there any other flags I can use to pass the parameters to the executable that is called by the self extractor.
I read the following documentation about the available flags.
http://www.winrar-tr.com/winrar/Help/ENG/html/HELPGUISFXCmd.htm
The parameters for the executable can be specified directly in the comment file with the parameters for the SFX module.
Here is an example batch file demonstrating this technique:
#echo off
cd /D "%TEMP%"
rem Create the file for the SFX module with the SFX options.
echo ;The comment below contains SFX script commands.>TestSetup.txt
echo.>>TestSetup.txt
echo Setup=Test.bat Switch "One more parameter">>TestSetup.txt
echo Overwrite=1>>TestSetup.txt
echo Title=Test Installation>>TestSetup.txt
echo Text>>TestSetup.txt
echo {>>TestSetup.txt
echo ^<font face='Arial'^>An SFX test which just shows how SFX module runs the installer.^<br^>^<br^>Just click on button Install or hit RETURN.^</font^>>>TestSetup.txt
echo }>>TestSetup.txt
rem Create the batch file executed by SFX archive.
echo #echo %%0 %%*>Test.bat
echo #pause>>Test.bat
echo #del %%0 ^>nul>>Test.bat
rem Create the SFX archive.
RAR.exe a -sfx -c -zTestSetup.txt TestSetup.exe Test.bat
rem Delete the created batch and comment file.
del Test.bat
del TestSetup.txt
rem Run the self-extracting archive. User has to press only RETURN.
start /wait TestSetup.exe
rem Delete the self-extracting archive.
:DeleteLoop
del TestSetup.exe >nul
if exist TestSetup.exe goto DeleteLoop
This batch file first creates in directory for temporary files the text file TestSetup.txt with the content:
;The comment below contains SFX script commands.
Setup=Test.bat Switch "One more parameter"
Overwrite=
Title=Test Installation
Text
{
<font face='Arial'>An SFX test which just shows how SFX module runs the installer.<br><br>Just click on button Install or hit RETURN.</font>
}
Important for you is the line starting with Setup=.
Test.bat is the file to execute after extraction.
Switch is an option to pass as first parameter to Test.bat.
"One more parameter" is a second parameter with spaces inside to pass to Test.bat which must be enclosed in double quotes because of the spaces.
Next the batch file continues with creation of Test.bat with content:
#echo %0 %*
#pause
#del %0 >nul
This little batch file just outputs with first line how it was called by the SFX archive, next waits for a key hit by the user and last deletes itself. So it does not really matter to which directory the batch file is extracted. The default is current directory which is the directory of the temporary files.
Then the batch file creates the SFX archive TestSetup.exe. For details on the used switches see Rar.txt in program files directory of WinRAR.
Pleae note that the line with Rar.exe works only without modification if the program files directory of WinRAR is included in environment variable PATH, or Windows fails to find Rar.exe which is the console version of WinRAR. Modify the line with complete path to Rar.exe in double quotes to get this line of the batch file working independent on included directories in PATH.
After the SFX RAR archive is created, the files Test.bat and TestSetup.txt are deleted as not needed anymore.
Now the created SFX archive TestSetup.exe is called and after hitting key RETURN and you see that the Test.bat is called with the 2 parameters as specified in TestSetup.txt.
The batch file deletes finally also the created SFX archive.