You have created complex batch script to do a job, typically a logon script in a domain with multiple workstations. It's not really practical to roll-out patched images every time we fix something, so scripting is the way to go. But often scripts should only run once, and running it a second time might cause dramas.

In this example we want to install a new version of a software, but before we can do that we need to do a clean-up and remove all the old versions. Unfortunatly there are popular free software that has frequent releases and updates with bundled agents, helpers, toolbars, etc. And some of them just installs in a new location, and doesn't remove the old version.

This leaves a mess that can affect performance and potential dramas with different versions still being active. And that version with a known exploit was it removed when you did the update? Or is it still there?

So we create our fantastic clean-up script, it removes all known versions first, and then we run the new installation. We want run the script automatically thru logon script so we don't have leave our warm chair alone!

In the script we could just uninstall all packages except the new one, but often a clean up with exceptions leaves dramas behind. It's just easier and cleaner to remove all first, and that also makes the clean-up script more reusable for the future.


We are gone need two batch scripts, one is the script that will be called by the logon script, and the other is the actual clean-up script. Let's have a quick look at diagram so we can visualize what we want to do:

Very simple logic really, and it keeps the "logon task" separate from the script that does real job. Since the logon script runs with higher credentials then the user we have access to HKLM in the registry, and this where we are storing information on which scripts have run before.


We are just gone use the same area as any other software packages uses HKEY_LOCAL_MACHINE\SOFTWARE, for this example we are going to use LocalCompany. Since we might also be using other keys in here we will add a subfolder called patches (HKEY_LOCAL_MACHINE\SOFTWARE\LocalCompany\patches).

When the script runs it checks the registry to see if a unique key exist, if it does it means that the script has run before and we will exit. If the key does not exist, we will execute the "real_cleanup_script.bat", and set the key in the registry.

Let's have a look at some working scripts, and examples. Notice the redirect of error output (2>NUL) used to keep the output to a minimum (reg query will complain when it can not find the key the first time).



SET REG_PATH=HKLM\Software\LocalCompany\patches

reg query "%REG_PATH%" 2>NUL | find /i "%ONETIME_PATCH_NAME%" 1>NUL 2>NUL

IF errorlevel 1 (
 ECHO First and only time this will run... calling the real script here..
 cmd /c real_cleanup_script.bat
 reg add "%REG_PATH%" /v "%ONETIME_PATCH_NAME%" /t REG_SZ /d "%DATE% %TIME%" /f 1>NUL
) ELSE (
 ECHO Sorry, we have done this before, not doing it again... ever!


REM Do smart things here..

ECHO Clean-up completed successfully..

Example of output when running the script first time, and second time:

First and only time this will run... calling the real script here..
Clean-up completed successfully..

Sorry, we have done this before, not doing it again... ever!

We use the scripts name and path as the registry key, and we set the key value to be date and time so we have a record when the patch was applied.

In the big_cleanup_once_task.bat I set the registry key variable to the running scripts filename (ONETIME_PATCH_NAME=%~n0%~x0), this could be a fixed name (ONETIME_PATCH_NAME="epic cleanup"), or even contain the scripts path and filename (ONETIME_PATCH_NAME=%0).

This article is based on a solution developed on some years ago. It was used as part of a domain logon script in a Windows XP environment.

Download example files used above:
Site maintained by
Page generated in: 0.0113 seconds.
Memory usage: 535944 bytes (peak: 551568 bytes)