Switch between two .reg files - batch-file

I'm looking for a quick and easy way (I don't need any error checking) to switch between two reg files by opening a batch file.
If a user runs a batch file, the batch file should merge reg file A to the registry. If the user runs it again, the batch file should merge reg file B to the registry. If the user runs it again, file A is merged... you get the point.
In general, I think there are two ways to do this:
Create some sort of variable to store which reg should be run next.
Check the registry key values to see which reg has been merged most recently (probably the preferred method).
Currently, I'm doing this:
REG QUERY "KeyName" /v "ValueName" | Find "x"
IF ERRORLEVEL 1 regedit /S file1.reg
IF ERRORLEVEL 0 regedit /S file2.reg
The REG QUERY part seems to work, but at the IF ERRORLEVEL statements something is going wrong. But maybe I should use a different method altogether.
Hoping for some suggestions.. Thanks in advance!
EDIT
Sorry for being a bit vague: I believe the previous solution didn't work, because when the first IF is correct, the second IF will be too after the first IF's command. So I will need an IF ELSE statement to prevent running the second IF.
I've now come up with this solution, which works:
REG QUERY "KeyName" /v "ValueName" | Find "x
IF ERRORLEVEL 1 (REGEDIT /S "file1.reg") ELSE REGEDIT /S "file2.reg"
I was also wondering: would it be an improvement to have the registry key/values added inside the batch file instead of using seperate .reg files? The value types are REG_BINARY and REG_DWORD.

I would try this:
REG QUERY "KeyName" /v "ValueName" | Find "x"
IF ERRORLEVEL 1 (
regedit /S file1.reg
goto :EOF
)
regedit /S file2.reg
The IF condition is set to TRUE when the ERRORLEVEL is equal to, or greater than, the ERRORLEVEL number (see here: http://support.microsoft.com/kb/39585/en-us) so the second IF condition is always evaluated as true.

You can store a value in a enviroment variable
#Echo OFF
:: By Elektro H#cker
Set | FIND "Merged" >NUL && Regedit /S "File_B.reg" || Regedit /S "File_A.reg" && SETX Merged YES >NUL
Pause&Exit
This is the same code but indented and with a quickly explanation:
#Echo OFF
:: By Elektro H#cker
REM If it's batfile first launch then I add a value "YES" to a variable and then only merges the File A.
REM If isn't batfile first launch then only merges FILE B
Set | FIND "Merged" >NUL && (
Regedit /S "File_B.reg"
) || Regedit /S "File_A.reg" && (
SETX Merged YES >NUL
)
Pause&Exit

Related

Check if registry key + value exists and if so, log it

I want to check if a certain registry key exists and if so, check its value as well
if it equals 0 (for example), then write to log: not found
if it equals 1 (for example), then write to log: found
should I stick to reg query and if structure or is there an easier method?
How do I check if a key is present in the windows registry
This can be done using reg query key:
This command will set %errorlevel%.
errorlevel=0 means the key exists.
errorlevel=1 means the key does not exist.
Example batch file
#echo off
Set mykey="HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run"^
^ "HKCU\Software\Microsoft\Windows\CurrentVersion\Run"^
^ "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"^
^ "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunServices"^
^ "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunServices"^
^ "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options"^
^ "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders"^
^ "HKEY_LOCAL_MACHINE\SOFTWARE\Hackoo"
Set LogFile=logkey.txt
If Exist %LogFile% Del %LogFile%
For %%K in (%mykey%) Do Call :Check_Key %%K %LogFile%
Start "" %LogFile%
Exit /b
:Check_Key
reg QUERY %1 >nul 2>&1
(
if %errorlevel% equ 0 ( echo %1 ===^> Found && reg QUERY %1
) else ( echo %1 ===^> Not found
)
) >>%2 2>&1
Further reading
reg - Read, Set or Delete registry keys and values, save and restore from a .REG file.
An A-Z Index of the Windows CMD command line is an excellent reference for all things Windows cmd line related.
Unfortunately, I haven't found a proper way to check if the value is actually correct. You can use a FOR loop and tokens= to locate the value and compare but what happens when the REG QUERY returns more tokens than you're expecting? Using FIND fails in both a simple REG QUERY | FIND and in the FOR loop because it always returns the wrong %ERRORLEVEL% beyond one level. Even with DelayedExpansion, it seems it will eventually fail.

Batch Script to display the filenames with extension (.skc) in mail body or at least put the .skc values in a variable from #file

I am still stuck with this. Can anyone of you please help me out to figure out how to achieve this.
First of all, thanks for all your help!
I am in need of a batch script which need to do the following.
Suppose a path is there (D:\test)
Script should go to the above path and search for text files as in ( D:\test*.skc)
If .skc files are found. It should trigger a mail where all the .skc files should be mentioned in the mail body.
This should be running all the time like daemons and trigger the mail only if .skc is found.
Please help me achieving this.
I tried doing something from my end, where i am able to put the .skc files in a log file. but getting results as expected above.
please find my work below.
#echo off
set file_path="D:\test"
forfiles /d -0 /p %file_path% /m *.skc /c "cmd /c echo #file" >> "D:\test\example.log"
Or at-least please help me get the following.
The below batch script which will pull out all the files with extension .skc from a specific path and all this will be written in #file as below.
forfiles /d -0 /p %file_path% /m *.skc /c "cmd /c echo #file"
I need to put this #file in a variable, like
output=#file
echo %output%
Can you please help me achieve this?
#ECHO OFF
SETLOCAL
SET "logfiledir=u:\destdir"
SET "monitordir=u:\destdir"
ECHO(skc files report>"%logfiledir%\log.1"
SET /a nextlog=0
:monitor
SET /a prevlog=1-nextlog
ECHO(skc files report>"%logfiledir%\log.%nextlog%"
dir /b /a-d "%monitordir%\test*.skc" >>"%logfiledir%\log.%nextlog%" 2>NUL
FINDSTR /v /g:"%logfiledir%\log.%prevlog%" ".skc" "%logfiledir%\log.%nextlog%" >NUL 2>nul
IF NOT ERRORLEVEL 1 (
ECHO(CALL BLAT using "%logfiledir%\log.%nextlog%"
)
SET /a nextlog=(nextlog + 1) %% 2
timeout /t 2 >nul
GOTO monitor
Hmm - interesting exercise.
This batch allows you to set up the directory to keep thisbatch's logfiles and the directory to monitor separately.
It maintains files log.1 and log.0 and looks for changes.
First step is to create a dummy previous-log file with a set string and then establish which is the next logfile to use.
Within the loop, we derive the previous logfile name and generate a new version of the current logfile with our set string
append to the current logfile a /b (bare - names only) /a-d (and no directorynames) directory list of the directory to monitor.
Find whether there are any lines in the new file that are not in the old (setting errorlevel 0 if so, non-zero if not)
Invoke the email if there were new entries. I use blat - you pays your money, you takes your choice...
Then change the next logfile identity
wait (I chose 2 seconds for testing) and repeat ad infinitum.
The problem with findstr is that it doesn't like an empty exclude file (/g:...) so identical strings need to be inserted into each log file as dummies.
Don't remove the timeout otherwise this procedure will become a processor-hog.

IF EXIST - Files Without an Extension

A working script that moves various files based on file name runs successfully. After the script is done it will check two directories for any lingering files using IF EXIST *.txt. This works great except I've noticed some files with no extension. These were not an issue before and since that cannot be helped due to processes out of my control, I need to amend my script.
My only idea is the following code. Bear with as there are two conditions:
:check1
PUSHD "\\UNC\path1" &&(
DIR /A-D *.
IF %errorlevel% NEQ 0 GOTO check2
) & POPD
:add1
ECHO Add note to the log file
:check2
PUSHD "\\UNC\path2" &&(
DIR /A-D *.
IF %errorlevel% NEQ 0 GOTO laststep
) & POPD
:add2
ECHO Add note to the log file
:laststep
Some other code before exiting
This should run DIR on the path and if files without extensions exist, it will have %errorlevel% zero and move on to the next check. If there are no files present, it will have %errorlevel% not zero (likely 1) and it will append some text to the log before the next check. Check two will do the same.
This seems to be awfully complicated and I am not able to find a "one-liner" solution that is as easy as IF EXIST. I realize I can use *. but that returns directories as well and may result in an incorrect %errorlevel%.
Updated Code
Where I normally set my variables, I also SET the two paths to run DIR against. This way they can be used more easily elsewhere and I bypass the UNC Path error I normally get - reasons for that are unknown to me. The updated file check, used only for files without an extension, is:
DIR %p1% /b /a-d|FIND /v "." && ECHO Found 1 >> %log%
DIR %p2% /b /a-d|FIND /v "." && ECHO Found 2 >> %log%
FINDSTR /I "Found" %log%
IF %errorlevel% EQU 0 GOTO stillthere
:nofiles
Some code
GOTO domore
:stillthere
Some code
:domore
Other code before exit
Thank you for the responses, I've learned from this.
Is this what you want to find?
dir /b /a-d |find /v "."
#ECHO OFF
SETLOCAL
:check1
PUSHD "u:\path1"
DIR /A-D *. >NUL 2>NUL
IF %errorlevel% EQU 0 ECHO Add note \path1 to the log file
POPD
PUSHD "u:\path2"
DIR /A-D *. >NUL 2>NUL
IF %errorlevel% EQU 0 ECHO Add note \path2 to the log file
POPD
:laststep
:: Some other code before exiting
GOTO :EOF
Your problems include:
Within a block statement (a parenthesised series of statements), the entire block is parsed and then executed. Any %var% within the block will be replaced by that variable's value at the time the block is parsed - before the block is executed - the same thing applies to a FOR ... DO (block).
Hence, IF (something) else (somethingelse) will be executed using the values of %variables% at the time the IF is encountered.
and you are potentially jumping out of a PUSHD/POPD bracket which would mean your POPD won't necessarily restore your starting directory.
(Note that I used u:\ rather than a server to suit my system)
You are already using && to verify PUSHD worked. You can do the same with your DIR /-D. I find it makes life easier. Also, you probably want to hide any error message if *. is not found, especially since that is the expected condition. I also hid the display of any files that might be found, but you can certainly get rid of that redirection. You might also want to hide error message if PUSHD fails, but I didn't implement that.
PUSHD "\\UNC\path1" && (
DIR /A-D *. 1>nul 2>nul && ECHO Add note to the log file
POPD
)
PUSHD "\\UNC\path2" && (
DIR /A-D *. 1>nul 2>nul && ECHO Add note to the log file
POPD
)
ECHO Some other code before exiting

For loop does not throw errorlevel of 1 when folder is empty

I have the following line in a batch script
for %%a in (*.rmt) do (findstr /C:" model='" %%a)>tmp.par
When I run this on an empty folder, the errorlevel is still 0.
However, if I replace *.rmt with a filename, say x.rmt, which doesnt exist in the folder either, the errorlevel becomes 1.
Ideally, if there are no RMT files in the folder, shouldnt the errorlevel!=0?
I require this For loop to work on *.rmt, as there might be 0 to multiple RMT files in a folder. Please help.
Thanks.
Note: If the string " model='" exists in one RMT file, it will compulsorily be present in all the other RMT files(if any) in the folder.
The findstr is never executed if there are no matches to the *.rmt, hence the errorlevel remains unchanged.
When you use x.rmt, FOR changes behaviour - it's no longer looking for a filename matching, it's looking at a particular string - which may or may not be a filename, which may or may not exist.
You could deliberately set errorlevel before the for
#ECHO OFF
SETLOCAL
ECHO y|FIND "x">nul
for %%a in (*.rmt) do (findstr /C:" model='" %%a)
ECHO errorlevel=%errorlevel%
GOTO :EOF
which will return errorlevel 1 unless the match is found.
Try this:
#echo off
for /F "delims=" %%i in ('dir /b "path_to_dir\*.rmt"') do (
:: echo Folder is NON empty
findstr /C:"model='" %%i >> C:\testlog.log
goto :EOF
)
No, the FOR command never sets the ERRORLEVEL <> 0 if there are no iterations.
Yes, the following command reports ERRORLEVEL=1:
for %%a in (notExists.rmt) do (findstr /C:" model='" %%a)>tmp.par
But that is because the simple FOR simply lists the string(s) within the IN() clause if they do not contain wildcards. It doesn't bother checking to see if the file exists. So your FINDSTR command is actually raising the error because it cannot find the file, not the FOR statement.
Your command is flawed in that each iteration overwrites the previous tmp.par. That can be easily fixed by adding an extra level of parentheses. This also will create an empty tmp.par if no files were found or if none of the files contained the search string. The ERRORLEVEL cannot be relied upon because its value will not have been set if no files were found, or it may be 0 or 1 depending on if the last file contained the search string.
(for %%a in (*.rmt) do (findstr /C:" model='" %%a))>tmp.par
If you don't mind having a filename: prefix on each line of output, then you can simplify your code to:
findstr /C:" model='" *.rmt >tmp.par 2>nul
This also will create an empty tmp.par file if no files were found, or if none of the files contain the search string. But now the ERRORLEVEL will be reliable. The ERRORLEVEL is 1 if no files are found or if no files contain the search string. Otherwise the ERRORLEVEL will be 0.

Why does this .bat cmd always hit a sub routine which I do not intend for it to hit?

I have the following in a BAT file:
#echo off
Set /P _environment = Please Enter Environment [d] for Development or [a] for Acceptance:
IF ((%_environment% EQU "a") OR (%_environment% EQU "d"))
(goto sub_write_files)
ELSE
(goto end)
:sub_write_files
xcopy script_temp\* \\CHU-%_environment%101\CHU\scripts /D /E /C /R /I /K /Y /S
:end
echo %_environment% Done
The logic seems well formed to me, but possibly it is not because the sub_write_files sub routine every time that I fire this command. I am assuming that the flaw is in the conditional logic.
You need to brush up on your batch syntax. Help is available for just about every command by typing either HELP command or command /? at a command prompt. For example, HELP IF will provide help on the IF command. Granted, the documentation is often incomplete and/or confusing, but it is a start.
You have lots of problems with your syntax as written. One of the most obvious is IF does not support any operators like AND, OR, XOR etc.
You can achieve the logic you were looking for with the following
#echo off
Set /P _environment = Please Enter Environment [d] for Development or [a] for Acceptance:
if "%_environment%" neq "a" if "%_environment%" neq "d" goto :end
:sub_write_files
echo xcopy script_temp\* \\CHU-%_environment%101\CHU\scripts /D /E /C /R /I /K /Y /S
:end
echo %_environment% Done
There are lots of potential improvements. For example, you might want to add the /I option to both IF statements so that case does not matter. Or you might want to loop back and try again instead of ending if an invalid value is entered.
The main problem is the complete wrong syntax of your code.
An IF-Statement only accepts one condition, you can not combine them with OR or AND.
It's not allowed to surrend the condition with parenthesis.
A beginning block has to start on the same line, also for the ELSE clause.
A set ... varname= with a space between varname and the equal sign creates a variable named varname<space>.
But the rest of your code should work ...
The logic seems well formed to me
Probably a simple IF /? would correct this.

Resources