0

I have a simple batch file that runs and deletes itself after running. This app was put on the desktop and will be executed using registry RUNONCE. To self delete it, I'm using this command below.

goto 2>nul & del /Q "%APP_PATH%"

Unlike this command below, the command above doesn't print any errors in the console.

del /Q "%APP_PATH%"

The batch file was deleted in the desktop. When we install our internal application (not recovery app), the batch file that was deleted using DEL command will be restored to its previous location. I haven't got a chance to check the internal application source code yet. By this level of information, does anyone has an idea of why this weird behavior happens?

Master James
  • 188
  • 3
  • 16
  • `del` just removes the pointer to the file, marking the occupied sectors as "free" (unlike deleting with explorer, which moves the file to the recycle bin) Chances are, your application doesn't "restore" the file, but writes a new copy. – Stephan Jan 11 '21 at 08:47
  • @Stephan but where would it get the details to write a new one? – Master James Jan 11 '21 at 09:13
  • inside the application.exe or it's installation routine. – Stephan Jan 11 '21 at 09:40
  • @Stephan This batch file was run through registry RUNONCE does it makes difference? – Master James Jan 11 '21 at 10:39
  • The successful deletion depends on a) the exact content of `%APP_PATH%`, b) the setting of the working folder for the task and c) on the permissions for the user the processes is bound to to the according folder. The "recreation" has nothing to do with that (as far as I can see). – Stephan Jan 11 '21 at 11:10

1 Answers1

1

The Windows command processor cmd.exe processes a batch file line by line. This means it opens a batch file, reads the next line, parses it, and if there is no more line to read, it closes the batch file. Then it executes the command(s) on the parsed line. See How does the Windows Command Interpreter (CMD.EXE) parse scripts?

The Windows command processor exits the processing of a batch file if there is a serious syntax here. This error condition handling is used here.

Create a batch file with following lines:

@echo off
goto
echo Third line!

Open a command prompt and run this batch file by typing its full qualified file name, i.e. drive + path + name + extension enclose in double quotes.

There is the following error message output by cmd.exe because of batch label is missing on second line.

No batch label specified to GOTO command.

The third line is not executed anymore by cmd.exe because of batch file processing is exited after execution of second command line because of this serious syntax error on which it is unclear for cmd.exe where to continue the batch file processing.

Now let us look on the command line:

goto 2>nul & del /Q "%APP_PATH%"

This is a command line with two commands on one line as described in detail by my answer on Single line with multiple commands using Windows batch file.

The first command goto with the missing batch label results in exiting the batch file processing. The error message output by cmd.exe in this case is redirected with 2>nul to device NUL to suppress it. But the second command del /Q "%APP_PATH%" with the already expanded environment variable %APP_PATH% is already in the commands queue. For that reason this command is executed next.

Then cmd.exe does not even try to open the batch file once more to read the third line as the invalid goto command results in exiting batch file processing which in this case does not even exist anymore if %APP_PATH% references the name of the batch file.

BTW: APP_PATH is a strange because of misleading environment variable name for a file name with full path.

Here is an even better example:

Create first a batch file with name Test1.cmd with following lines:

@echo off
echo %~nx0 is calling Test2.cmd.
call "%~dp0Test2.cmd"
echo %~nx0 is processed further.

Create second a batch file with name Test2.cmd with following lines:

@echo off
set "BatchFile=%~f0"
echo %~nx0 is deleting itself now.
goto 2>nul & del /A /F "%BatchFile%"

Then run from within a command prompt window Test1.cmd. The output is:

Test1.cmd is calling Test2.cmd.
Test2.cmd is deleting itself now.
Test1.cmd is processed further.

It can be seen that Test2.cmd deleted itself without showing any error message by cmd.exe processing Test2.cmd. But processing of Test1.cmd is continued after Test2.cmd deleted itself.

The option /Q is not really necessary on deleting a single file and the file definitely exists on running the command. The option /A is useful to delete the batch file even if it has the hidden attribute set as otherwise del would not delete it. The option /F is useful to delete the batch file even if the read-only attribute is set.

Another command method is using as last command line in a batch file which should delete itself the command line:

del /A /F "%~f0" & exit

But it has a disadvantage as it can be seen on creating a Test2.cmd with the lines:

@echo off
echo %~nx0 is deleting itself now.
del /A /F "%~f0" & exit

Run Test1.cmd from within the command prompt window. The batch file Test2.cmd deletes itself, but command exit results in exiting the cmd.exe opened with opening the command prompt window and processing both batch files. For that reason Test1.cmd is not further processed and the console window is closed immediately.

Appending the option /B after command exit would result in not exiting cmd.exe, but two error messages would be output by cmd.exe because of not finding anymore Test2.cmd.

For that reason the usage of goto 2>nul & del /A /F "%~f0" is a best practice example for self-deletion of a batch file.

BTW: The order or the two commands matters. The usage of del /A /F "%~f0" & goto 2>nul would result in an error message output by cmd.exe as in this case it tries to open the already deleted batch file once more.

Mofi
  • 38,783
  • 14
  • 62
  • 115