Is there a way of checking file availability in a DOS script? - windows

Background: I have a post-build process that copies a file to another location. It looks like this:
copy $(TargetPath) "%programfiles%\mypath"
This step can fail if the another process is using the file. The step is not critical, so if possible I would like to ignore the failure. To do this I need the script to check to determine if the file is being used by another process.
Question: Is there a way of testing a file in a DOS script to determine if it is being used by another process?

You can see if the file exists, then rename a .dll/.exe even if it is being executed. Might want to do .pdb files, too.
IF EXIST $(TargetName).deleted del $(TargetName).deleted
IF EXIST $(TargetName).pdb.deleted del $(TargetName).pdb.deleted
IF EXIST "%programfiles%\mypath\$(TargetName)$(TargetExt)" REN "%programfiles%\mypath\$(TargetName)$(TargetExt)" $(TargetName).deleted
IF EXIST "%programfiles%\mypath\$(TargetName)$(TargetExt)" REN "%programfiles%\mypath\$(TargetName)$.pdb" $(TargetName).pdb.deleted
copy $(TargetPath) "%programfiles%\mypath"

Ok, so I needed to check the errorlevel after performing the copy, so that I could handle the exit properly. The solution is below:
copy $(TargetPath) "%programfiles%\mypath"
if errorlevel 1 goto BuildProcessFailed
goto BuildProcessOK
:BuildProcessFailed
echo BUILDPROCESS FAILED FOR PROJECT $(ProjectName)
goto ExitBuildProcess
:BuildProcessOK
echo BUILDPROCESS OK FOR PROJECT $(ProjectName)
:ExitBuildProcess

Related

Generate error at the end of the copy if any files are not copied

I have the one batch that does the copy of some files in the network, this copy updates the previous files by the newest case they already exist in the destination folder, however if any file is in use the system does not present the error message at the end only in the Moment you are trying to update the file.
At the moment I do not want to solve this file problem being in use, I would only like the command to report only at the end of the copy if there was an error in updating some file.
I put in the end the condition if "%errorlevel%" == "0" but this condition does not work if there were errors in the middle of the copy.
My command:
xcopy "C:\origin\." "C:\destination\" /c /d /e /h /i /k /r /y
What I suggest for you is to loop through the folder and check if each file is in use, and then you can write the name of that file to some type of log, maybe a .txt file to read later to show what could not be overwritten.
2>nul (
>>FILE.EXT (call )
) && (echo file is not locked) || (echo file is locked)
This code, which I found at StackOverflow (dbenham deserves all the credit for this) could be used to check if a file is locked. Replace FILE.EXT with your file name, preferably in a loop to easily check every file, and if the file is locked echo the file name to a (temporary) .txt file and once completed, loop through that text file to list the results.
An added benefit to this is, if you check for files in use before trying to overwrite, you could skip files you know you can't write to thus saving a bit of time per file.

Can I prevent a batch file to be executed by more than 1 user at the same time

I have a batch file which can update a web project and clean/rebuild it. I made it executable for network users. Now I want to make the batch executable only by one user at the same time. Like synchronize object in programming languages.
Is there a possibility to do that?
A simple solution to check if batch file is already running is using file system.
The batch file can check if a file exists and denies execution in this case, otherwise it creates the file, runs the commands and finally deletes the file.
#echo off
if exist "C:\Temp\BatchLock.txt" goto BatchRunning
echo Batch file is running by %username%.>C:\Temp\BatchLock.txt
rem All other commands of the batch file
del C:\Temp\BatchLock.txt
goto :EOF
:BatchRunning
type C:\Temp\BatchLock.txt
echo/
echo Please run the batch later again.
echo/
echo Press any key to exit ...
pause >nul
Of course C:\Temp is not a good storage location for the lock text file. It must be a directory which is identical for all users, a directory on server with write permissions for all users.

How would I run a batch program from another batch program within its own environment?

I need to run a batch file located in another folder that must be called from another batch file.
Whenever I do call this batch file from the first, let's call them Batch_A and Batch_B, respectively, the second tries to run from the directory of the first batch file.
Batch_A needs to call or start Batch_B, however Batch_B needs to run as if I were to manually double-click it myself.
This is what I currently have at the end of my first batch
start "A thing" "%output%\thing.bat" /b
Have you looked into push or pop.
Before calling the second batch file, enter the "push" command:
pushd %dynamicdirectory%
Call batchfileb.bat
popd
If Batch_B is designed/written to be always run from the direcory where it is located
you might also consider to modify Batch_B.bat
setlocal
cd /D %0\..
REM your original content
endlocal
In %0 the path to the batchfile is stored.
The trick is to assume %0 is a directory then to change one level lower
based on that diretory.
With /D also the drive letter is changed correctly.
The cd command doesn't care if %0 is really a directory.
In fact %d doesn't even have to exist (%0\dummy\..\.. would also work).
The setlocal command is to have the working directory beeing restored
when Batch_B.bat has finished.
I noticed that the endlocal command is not really necessary
in this context since it is applied imlicitely when Batch_B finishes.

using space in path for copying files using batch script

I want to copy all the *.jar files to another directory i wrote the below script
echo Enter path to ILM_HOME:
set /p ILM_HOME=
echo Deployment in progress
copy WEB-INF/lib/*.jar "%ILM_HOME%"/webapp/WEB-INF/lib
I use C:\Documents and Settings\asimon\Desktop\test as my input
It gives me syntax of the command is incorrect
I think the problem is Documents and Settings I even put "%ILM_HOME%" and I don't need c:\Docume~1\asimon\Desktop\test any other solution?
Update
This is working
#echo off
echo
echo Enter path to ILM_HOME:
set /p ILM_HOME=
IF EXIST "%ILM_HOME%\stopApplimation.bat" (
echo Deployment in progress
xcopy WEB-INF\lib\*.jar "%ILM_HOME%\webapp\WEB-INF\lib"
CALL "%ILM_HOME%\stopApplimation.bat"
CALL "%ILM_HOME%\startApplimation.bat"
) ELSE (
echo %ILM_HOME% path is incorrect.
)
also any linux solution is also helpfull with .sh for the below 2 statements
"%ILM_HOME%/stopApplimation.bat"
"%ILM_HOME%/startApplimation.bat"
for linux, how can i replace the above 2 statements?
$ILM_HOME/stopApplimation.sh
$ILM_HOME/startApplimation.sh
Did you try
xcopy WEB-INF\lib\*.jar "%ILM_HOME%\webapp\WEB-INF\lib"?
EDITED:
In your batch use CALL "%ILM_HOME%\stopApplimation.bat"

Does a bat file know its name and can it delete itself

At some point in my script, I'd like the bat script to delete itself. This requires that the script know its name and then to use that name to delete itself. Is this possible?
None of the existing answers provide a clean way for a batch file to delete itself and exit without any visible error message.
Simply including del "%~f0" does delete the script, but it also results in an ugly "The batch file cannot be found." error message.
If it is OK for the script to close the parent CMD process (the console window), then the following works fine without any error message:
del "%~f0"&exit
But it is a bit more complicated if you want the script to delete itself and exit without closing the parent CMD process, and without any error message.
Method 1: Start a second process that runs within the same console window that actually performs the delete. The EXIT /B is probably not necessary, but I put it in to maximize the probability that the batch script will close before the STARTed process attempts to delete the file.
start /b "" cmd /c del "%~f0"&exit /b
Method 2: Create and transfer control to another temp batch file that deletes itself as well as the caller, but don't use CALL, and redirect stderr to nul.
>"%~f0.bat" echo del "%~f0" "%~f0.bat"
2>nul "%~f0.bat"
If I'm not mistaken, %0 will be the path used to call the batch file.
Tested and working:
del %0
exit
%0 gives you the relative path the from the directory where the bat file was started. So if you call it
mybats\delyourself.bat tango roger
%0 will contain mybats\delyourself.bat
del %0 works if you haven't changed your current directory.
%~f0 exapnds to the full path to the file.
For me it was important, that I have no errorLevel 1 after I exited the batch file. I found an suitable and easy answer this way:
DeleteMyself.cmd:
START CMD /C DEL DeleteMyself.cmd
Test batch if DeleteMyself.cmd is returning errorLevel 0. TestDeleteMyself.cmd:
call DeleteMyself.cmd
echo Errorlevel: %errorLevel%

Resources