I'm currently learning how to create batch scripts, but so far I am doing just queries. I am able to get a list of the current hardware, device map and serial com on the following registry path
HKLM\hardware\devicemap\serialcomm
The problem is that every computer is displaying a different serialcomm on the same device. So I am trying to capture the serialcomm based on the device name.
My current code below:
reg query HKLM\hardware\devicemap\serialcomm
pause
Below is an updated code I have tried to get the serialcomm based on the hardware name, but is not working :(
set "Comm="
reg query HKLM\hardware\devicemap\serialcomm
if %%hardware%% = ProlificSerial0 set Comm=%%serialcomm%%
pause
The above code was created based on all the information I have found on multiple websites, but as I said, I am still learning queries and it is a little bit complicated for me adding more code.
I will appreciate if anybody can tell me what is wrong with the updated code.
Here is a batch code with some explaining comments which I wrote a few weeks ago to program Atmel AVR controllers via a batch file using mySmartUSB MK2 being mounted as virtual serial communication port after having once the device driver installed. The code part for programming the fuse bits, flash and eeprom of the AVR controllers is replaced here by a simple information message.
The batch file determines the COM port number
from one of several optional command line parameters (special option), or
queries it automatically directly from Windows registry (default method), or
asks the user of the batch file for the port number (fail safe method).
For the question the identification from Windows registry is the most interesting part.
DeviceInstance, HardwareID and ProductName must be adapted for the Prolific USB-to-Serial converter.
Look with Windows registry editor on registry key
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB
for the device instance identifier and hardware identifier (vendor and product identifier) for the Prolific USB-to-Serial converter.
#echo off
setlocal EnableExtensions
set "ComPort="
set "DeviceInstance=mySmartUSB2-0001"
set "HardwareID=VID_10C4&PID_EA60"
set "ProductName=mySmartUSB MK2"
cls
echo.
call :ProcessArguments %*
call :CheckPort
echo Serial port of %ProductName% is: COM%ComPort%
echo.
endlocal
pause
goto :EOF
rem The subroutine ProcessArguments processes the optional parameters of
rem the batch file. For this demo everything except COMx with x being a
rem number in range 1 to 255 is interpreted as unknown parameter.
:ProcessArguments
set "EmptyLine=0"
:NextArgument
if "%~1" == "" (
if "%EmptyLine%" == "1" echo.
goto :EOF
)
set "SerialPort=%~1"
if /I "%SerialPort:~0,3%" == "com" (
set "ComPort=%SerialPort:~3%"
) else (
echo ERROR: Unknown parameter: %1
set "EmptyLine=1"
)
shift
goto NextArgument
rem The subroutine CheckPort checks the port number specified as parameter
rem on calling the batch file.
rem In case of no COM port number was specified as parameter, it attempts
rem to determine the COM port number for the device as defined at top of
rem the batch file directly from Windows registry. The registry query is
rem written to work for Windows XP and any later Windows.
rem Last in case of a valid COM port was whether passed to the batch file
rem via COMx parameter nor could the port number be determined from Windows
rem registry automatically, the user is prompted in a loop to enter a valid
rem port number.
:CheckPort
set "EmptyLine=0"
if not "%ComPort%" == "" goto VerifyPort
for /F "skip=2 tokens=1,3" %%A in ('%SystemRoot%\System32\reg.exe QUERY "HKLM\SYSTEM\CurrentControlSet\Enum\USB\%HardwareID%\%DeviceInstance%\Device Parameters" /v PortName 2^>nul') do (
if /I "%%A" == "PortName" set "SerialPort=%%B" && goto GetPortNumber
)
goto EnterPort
:GetPortNumber
if /I "%SerialPort:~0,3%" == "com" (
set "ComPort=%SerialPort:~3%"
goto VerifyPort
)
:EnterPort
set "EmptyLine=1"
set "ComPort=4"
set /P "ComPort=Enter number of COM port (default: %ComPort%): "
:VerifyPort
for /F "delims=0123456789" %%I in ("%ComPort%") do set "ComPort="
if "%ComPort%" == "" goto EnterPort
if %ComPort% EQU 0 goto EnterPort
if %ComPort% GTR 255 goto EnterPort
if "%EmptyLine%" == "1" echo.
goto :EOF
I think, processing HKLM\HARDWARE\DEVICEMAP\SERIALCOMM is not advisable as it lists all serial devices including for example also modems and not only serial ports. Also with hardware identifier known for the device, the COM port number can be found out more quickly directly as demonstrated above.
The DeviceInstance identifier often ends with an incrementing number in case of several devices with same vendor and product identifier are connected at the same time on different USB ports.
So for supporting multiple Prolific USB-to-Serial converters connected on same computer it would be better to query first just the hardware identifier to get all device instance identifiers.
Here is a very simple example for ATEN USB to Serial Bridge adapter:
#echo off
setlocal EnableExtensions
set "HardwareID=VID_0557&PID_2008"
set "RegistryPath=HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB"
set "ProductName=ATEN USB to Serial Bridge"
set "DeviceFound=0"
cls
echo.
for /F "delims=" %%I in ('%SystemRoot%\System32\reg.exe QUERY "%RegistryPath%\%HardwareID%" 2^>nul') do call :GetPort "%%I"
if "%DeviceFound%" == "0" echo WARNING: Could not find any %ProductName%.
echo.
endlocal
pause
goto :EOF
:GetPort
set "RegistryKey=%~1"
if /I not "%RegistryKey:~0,71%" == "%RegistryPath%\%HardwareID%\" goto :EOF
for /F "skip=2 tokens=1,3" %%A in ('%SystemRoot%\System32\reg.exe QUERY "%~1\Device Parameters" /v PortName 2^>nul') do (
if /I "%%A" == "PortName" set "SerialPort=%%B" && goto OutputPort
)
goto :EOF
:OutputPort
set "DeviceFound=1"
set "DeviceNumber=%RegistryKey:~-1%"
echo %DeviceNumber%. %ProductName% is %SerialPort%.
goto :EOF
Note: Both batch code examples do not check if each found device is really currently connected to the computer. That would require additional code whereby even cross-checking with values registered currently under HKLM\HARDWARE\DEVICEMAP\SERIALCOMM is not enough as this registry key is not automatically updated when a (virtual) serial COM port device is unplugged. It is only always updated when a serial COM port device is plugged in.
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 /?
cls /?
echo /?
endlocal /?
for /?
goto /?
if /?
pause /?
reg /?
reg query /?
rem /?
set /?
setlocal /?
shift /?
I have no serialcomm on my machine but you can use this as reference:
#echo off
for /f "tokens=3* delims= " %%a in (
'reg query HKLM\hardware\devicemap\pointerclass'
) do (
set "pointer=%%a"
)
echo %pointer%
if "%pointer%" equ "REGISTRY\MACHINE\SYSTEM\ControlSet001\Services\mouclass" echo need to set something
You should pass the specific value you are looking for as an argument to your batch file. For instance, if your batch file is named RegSearch, the command line syntax should be Something like:
RegSearch ProlificSerial0
You should therefore do a little bit of syntax checking inside the batch file to make sure you aren't forgetting to specify the argument when you run the batch file.
In addition, you can add the /v parameter to the Reg Query command in order to look for a specific value (rather than looking through all the keys). You can then filter the query results with findstr to determine if it was successful.
The following code should do all of that:
#echo off
setlocal enabledelayedexpansion
if /i "%1"=="" goto syntax
set myValue=%1
for /f "tokens=3 delims= " %%a in ('reg query hklm\hardware\devicemap\serialcomm /v *%myValue%* ^| findstr /i %myValue%') do (
set comm=%%a
echo !comm!
)
goto :eof
:syntax
echo.
echo ERROR : invalid syntax. You must pass the value to look for as the first argument, for example:
echo RegSearch Prolificserial0
Related
#echo off
:prep
cls
for /f "tokens=2-4 delims=/ " %%a in ('date /t') do (set mydate=%%c-%%a-%%b)
:for /l %A in (1,1,100) do copy "C:\some folder\file.ext" "C:\some folder\file-%%A.ext"
set choice=
:: test to see if directory exists
if EXIST "../delivery_%mydate%.txt" (
goto overwrite
) else (
goto start
)
:overwrite
echo.
echo delivery note already exists - continue?
set /p choice='y / n ?'
if '%choice%'=='' ECHO "%choice%" is not valid please try again
if '%choice%'=='y' goto start
if '%choice%'=='n' goto end
echo.
:start
echo.
for /l %A in (1,1,100) do copy "C:\some folder\delivery_%mydate%.ext" "C:\some folder\delivery_%mydate%.ext"
echo Choose the following:
echo 1. Directories
echo 2. Files
echo 3. quit
echo.
set /p choice=
if '%choice%'=='1' goto directory
if '%choice%'=='2' goto file
if '%choice%'=='3' goto end
cls
ECHO "%choice%" is not valid please try again
goto start
:directory
dir /ad /on /b > ../delivery_%mydate%.txt
echo.
goto checksuccess
:file
dir /a-d /on /b > ../delivery_%mydate%.txt
echo.
goto checksuccess
:checksuccess
I need to add a line of code to this batch file I have created above. I need this code to save an existing file to a higher version without deleting the previous one. This will also need to be embedded into the code I created. For example it will start saving them like: filev001, filev002, etc.
1. Some general advice for writing batch files
A list of commands is output on executing in a command prompt window help. It is advisable to use in batch files for environment variables and labels not a string which is also a command. It is possible, but not advisable.
start is a command to start an application in a separate process. So it is better to use for example Begin instead of start as label.
choice is a command for a choice which is better for single character choices than using set /P. So it is better to use for example UserChoice instead of just choice as environment variable name.
It is better to use echo/ instead echo. to output an empty line. The reason is explained by DosTips forum topic ECHO. FAILS to give text or blank line - Instead use ECHO/.
Environment variable names and labels are easier to read on using CamelCase and can be more easily searched case-sensitive and if necessary replaced in a batch file than a name/label which can exist as word also in comments and in strings output with echo.
The answer on question Why is no string output with 'echo %var%' after using 'set var = text' on command line? explains in detail why the usage of the syntax set "Variable=string value" is recommended in batch files on assigning a string to an environment variable.
The directory separator on Windows is the backslash character \. The slash character / is the directory separator on Unix/Linux/Mac. On Windows / is used for options/parameters. The Windows kernel functions support also directory and file paths with / as directory separator by automatically correcting them to \ internally in path. But it is nevertheless recommended to use in a batch file \ in paths.
rem is the command for a comment in a batch file. :: is an invalid label and not really a comment. Lines with a label at begin are ignored for command execution. But a label cannot be used in a command block. For that reason it is recommended to use command rem because :: in a command block results often in unexpected behavior on execution of the batch file.
2. Get current date in a specific format
Let us look on the command line:
for /f "tokens=2-4 delims=/ " %%a in ('date /t') do (set mydate=%%c-%%a-%%b)
date /t is a command which for executes in a background command process with the command line cmd.exe /C date /t for capturing the output of this command process written to standard output handle STDOUT and process the captured output line by line.
Can this be optimized?
Yes, because on running in a command prompt window set /? and reading the output help from first to last page it can be read that there is the environment variable DATE which expands to current date. So there is no need to run the command date to get current date as string.
The command date with option /t outputs the current date in the format defined for the used user account in Windows Region and Language settings. In your case it looks like the region dependent date format is MM/dd/yyyy with the weekday abbreviation at beginning (with no comma) before the date. The date format on my computer is just dd.MM.yyyy without weekday. The environment variable DATE is in same region dependent format as output of command date /t.
So the region dependent date in format ddd, MM/dd/yyyy could be also modified to yyyy-MM-dd using the command line:
for /F "tokens=2-4 delims=/, " %%a in ("%DATE%") do set "MyDate=%%c-%%a-%%b"
It is also possible to use string substitution:
set "MyDate=%DATE:~-4%-%DATE:~-10,2%-%DATE:~-7,2%"
String substitution is also explained by help output on running set /? and read the answer on
What does %date:~-4,4%%date:~-10,2%%date:~-7,2%_%time:~0,2%%time:~3,2% mean?
But if yyyy-MM-dd is the wanted date format for current date independent on region settings of the used user account is advisable to use the command lines
for /F "tokens=2 delims==." %%I in ('%SystemRoot%\System32\wbem\wmic.exe OS GET LocalDateTime /VALUE') do set "MyDate=%%I"
set "MyDate=%MyDate:~0,4%-%MyDate:~4,2%-%MyDate:~6,2%"
This region independent solution is really much slower than the above command lines. It is explained in detail by the answer on Why does %date% produce a different result in batch file executed as scheduled task? But it has the big advantage of being region independent.
3. Prompting user for a single character choice
The usage of set /P variable=prompt is not recommended for a single character choice because
the user can just hit RETURN or ENTER without entering anything at all resulting in variable keeping its current value or still not being defined if not defined before set /P command line;
the user can make a typing mistake and presses for example Shift+2 instead of just 2 resulting (on German keyboard) to enter " as string which most batch files using set /P breaks because of a syntax error on next command line evaluating the user input;
the user can enter anything instead of one of the characters asked for including strings which on next command line results in deletion of files and folders.
The solution is using the command choice if that is possible (depends on Windows version). choice waits for the key press of a character specified in the command options and immediately continues after one of these keys is pressed. And choice exits with the index of the pressed character in list as specified in batch file. This exit code is assigned to ERRORLEVEL which can be evaluated next also within a command block without using delayed expansion or used directly in a single goto instruction.
4. Rewritten batch file
Here is the rewritten batch file:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem set "Folder=C:\some folder"
set "Folder=F:\Temp\Test"
:Prepare
cls
rem Get current date region independent in format yyyy-MM-dd.
for /F "tokens=2 delims==." %%I in ('%SystemRoot%\System32\wbem\wmic.exe OS GET LocalDateTime /VALUE') do set "MyDate=%%I"
set "MyDate=%MyDate:~0,4%-%MyDate:~4,2%-%MyDate:~6,2%"
set "FileNumber=0"
for %%I in ("%Folder%\file-*.ext") do call :GetFileNumber "%%~nI"
goto IncrementNumber
rem Subroutine to find out highest file number without using delayed
rem environment variable expansion for number range 0 to 2147483647.
rem Numbers starting with 0 are interpreted as octal number in number
rem comparison which makes it necessary to remove leading 0 from the
rem number string get from file name starting with 5 characters.
:GetFileNumber
set "Number=%~1"
set "Number=%Number:~5%
:RemoveLeadingZero
if "%Number%" == "" goto :EOF
if "%Number:~0,1%" == "0" set "Number=%Number:~1%" & goto RemoveLeadingZero
if %Number% GTR %FileNumber% set "FileNumber=%Number%"
goto :EOF
rem Make sure the file number has at least 3 digits.
:IncrementNumber
set /A FileNumber+=1
if %FileNumber% GEQ 100 goto ExistDelivery
set "FileNumber=00%FileNumber%"
set "FileNumber=%FileNumber:~-3%"
rem Test to see if file exists already.
:ExistDelivery
if not exist "..\delivery_%MyDate%.txt" goto Begin
echo/
%SystemRoot%\System32\choice.exe /C YN /N /M "Delivery note already exists, continue (Y/N)? "
if errorlevel 2 goto :EOF
:Begin
set "FileName=file-%FileNumber%.ext"
copy "%Folder%\file.ext" "%Folder%\%FileName%" >nul
echo/
echo Choose the following:
echo/
echo 1. Directories
echo 2. Files
echo 3. Quit
echo/
%SystemRoot%\System32\choice.exe /C 123 /N /M "Your choice? "
if errorlevel 3 goto :EOF
if errorlevel 2 goto GetFileList
dir * /AD /ON /B >"..\delivery_%MyDate%.txt"
echo/
goto CheckSuccess
:GetFileList
dir * /A-D /ON /B >"..\delivery_%MyDate%.txt"
echo/
:CheckSuccess
rem More commands.
endlocal
It was not really clear for me what the entire batch code is for at all.
It would have been also easier to write the determination of highest number in a file name on knowing the possible number range like 001 to 100. So I wrote a general solution for 001, 002, ..., 099, 100, 101, ..., 1000, ..., 2147483647.
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 /?
cls /?
copy /?
dir /?
echo /?
endlocal /?
for /?
goto /?
if /?
rem /?
set /?
setlocal /?
wmic /?
wmic os /?
wmic os get /?
wmic os get localdatetime /?
See also answer on Single line with multiple commands using Windows batch file for an explanation of & operator and read the Microsoft article about Using command redirection operators.
May be out of line here but I stumbled on a batch script here on Stack Overflow and it was just what I wanted to do. But it is a quit old post and I can't get it to work.
Original post: Batch to query registry key, find a string within that key, then create a new key
:start
setlocal ENABLEDELAYEDEXPANSION
set qry=reg query "HKLM\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002bE10318}" /s /v DriverDesc
for /f "Tokens=*" %%p in ('%qry%') do (
set var=%%p
set var=!var:^&=!
set var=!var:^)=!
set var=!var:^(=!
call :parse
)
endlocal
goto :EOF
:parse
if /i "%var:~0,5%" NEQ "HKEY_" goto parse1
set key=%var%
set key=%key:HKEY_LOCAL_MACHINE=HKLM%
goto :EOF
:parse1
setlocal ENABLEEXTENSIONS
for /f "Tokens=*" %%f in ('#echo %var%^|findstr /i /c:"Intel(R)"') do (
if defined key reg add %key% /v PnPCapabilities /t REG_DWORD /d 56 /f&set key=
)
endlocal >nul 2>&1
I executed this batch file on Windows 10 Home Edition and it has not changed anything in Windows registry although running it as administrator.
Can someone please help me to get this script to work?
Result of reg query:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002bE10318}\0000
DriverDesc REG_SZ Microsoft Kernel Debug Network Adapter
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002bE10318}\0001
DriverDesc REG_SZ Intel(R) Ethernet Connection I217-V
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002bE10318}\0002
DriverDesc REG_SZ Qualcomm Atheros AR946x Wireless Network Adapter
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002bE10318}\0003
DriverDesc REG_SZ Broadcom 802.11ac Network Adapter
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002bE10318}\0004
DriverDesc REG_SZ Bluetooth Device (RFCOMM Protocol TDI)
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002bE10318}\0005
DriverDesc REG_SZ Microsoft Wi-Fi Direct Virtual Adapter
The batch file written by Matt M does not work because all &, ( and ) are removed from all lines before calling the subroutine parse. For that reason Intel(R) is modified already to IntelR and FINDSTR cannot find in any modified line the string Intel(R). That's why reg add is never executed by batch file posted in question.
I decided to rewrite the batch code for the task to disable power management on all Intel ® network adapters.
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "DetectionCount=0"
for /F "delims=" %%I in ('%SystemRoot%\System32\reg.exe query "HKLM\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002bE10318}" /s /v DriverDesc 2^>nul') do call :ProcessLine "%%I"
if not %DetectionCount% == 0 echo/ & pause
endlocal
goto :EOF
:ProcessLine
set "RegistryLine=%~1"
if "%RegistryLine:~0,5%" == "HKEY_" set "RegistryKey=%~1" & goto :EOF
for /F "tokens=2*" %%A in ("%~1") do set "AdapterDescription=%%B"
if "%AdapterDescription:Intel(R)=%" == "%AdapterDescription%" goto :EOF
echo/
%SystemRoot%\System32\reg.exe add "%RegistryKey%" /v PnPCapabilities /t REG_DWORD /d 56 /f >nul
if errorlevel 1 (
echo Failed to add double word value "PnPCapabilities" with value 56 for
) else (
echo Added successfully double word value "PnPCapabilities" with value 56 for
)
echo network adapter "%AdapterDescription%" at registry key:
echo %RegistryKey%
set /A DetectionCount+=1
goto :EOF
How was the batch file tested?
I tested the script with the posted output of registry query
reg query "HKLM\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002bE10318}" /s /v DriverDesc
copied into text file RegistryOutput.txt and using the FOR loop
for /F "delims=" %%I in (RegistryOutput.txt) do call :ProcessLine "%%I"
instead of the FOR loop in posted batch code processing the output of the registry query directly. The line with reg.exe add was disabled by putting echo at beginning of this line.
The output of the batch file was:
Added successfully double word value "PnPCapabilities" with value 56 for
network adapter "Intel(R) Ethernet Connection I217-V" at registry key:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002bE10318}\0001
How does the batch file work?
The FOR command executes console application REG in a background command process with the command line:
C:\Windows\System32\cmd.exe /c C:\Windows\System32\reg.exe query "HKLM\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002bE10318}" /s /v DriverDesc 2>nul
REG could output an error message to handle STDERR if it cannot find the specified registry key. This is very unlikely because this is the registry key for network adapters. However, the error message would be redirected to device NUL to suppress it using 2>nul. Please read the Microsoft article about Using Command Redirection Operators for details about input and output redirection. The redirection operator > must be escaped here with caret character ^ to be interpreted as literal character when Windows command interpreter processes the entire FOR command line before executing internal command FOR. Otherwise 2>nul would be interpreted as misplaced redirection of command FOR resulting in a syntax error message by Windows command interpreter instead of running FOR.
The output of REG written to handle STDOUT in background command process is captured by FOR and then processed line by line.
Empty lines are skipped by FOR as well as lines starting with a semicolon which does not occur here because no line ever starts with a semicolon.
All other lines would be split up into substrings (tokens) using space and horizontal tab characters as delimiters for the strings. This split behavior is not wanted here. Therefore "delims=" is used to disable line splitting and get assigned to loop variable I each non empty line.
The line with a registry key or registry value DriverDesc is passed enclosed in double quotes to subroutine ProcessLine as first and only argument. An argument string must be enclosed in double quotes if it contains 1 or more spaces or 1 or more of following characters: &()[]{}^=;!'+,`~|<>
The subroutine ProcessLine assigns first the passed line without the double quotes to environment variable RegistryLine.
A line on which the first 5 characters are case-sensitive equal to string HKEY_ is interpreted as line with a registry key assigned to environment variable RegistryKey and the subroutine is exited with goto :EOF.
Otherwise the registry line with a DriverDesc is processed as string by one more FOR loop.
The option "tokens=2*" results in splitting up the line into the three parts:
DriverDesc
REG_SZ
The string starting with first non whitespace character REG_SZ up to end of line.
The second substring (token) REG_SZ is assigned to loop variable A. This string is of no interest for this task. For that reason loop variable A is not referenced by command line executed by FOR.
The third token being the network adapter description is assigned to next loop variable after specified loop variable A according to ASCII table which is B. That is the reason why loop variables are case-sensitive while environment variables are not.
The description of the driver of the network adapter is assigned to variable AdapterDescription for further processing.
The IF condition compares the adapter description with all occurrences of Intel(R) case-insensitive replaced by an empty string and therefore removed from the description with the unmodified network adapter description. Equal strings means the network adapter description does not contain the string Intel(R) resulting in exiting the subroutine with no further processing. In other words the registry key of this network adapter is ignored by the batch file.
But the double word value PnPCapabilities is added to the registry key containing this description value with the decimal value 56 for a network adapter with Intel(R) in description most likely at beginning of the description.
All other lines of the batch file are for informing the user of the batch file if any Intel ® network adapter was detected at all and if the registry value could be successfully added to registry or if that failed, for example on not running this batch file as administrator required for write access to any key of registry hive HKEY_LOCAL_MACHINE.
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 /?
echo /?
endlocal /?
for /?
goto /?
if /?
pause /?
reg /?
reg add /?
reg query /?
set /?
setlocal /?
See also the Microsoft support article Testing for a Specific Error Level in Batch Files. The answer on Single line with multiple commands using Windows batch file explains operator &.
I am writing bat-file to use several executable files (tools that I cannot change) sequentially.
Firs of the tool receive two file names and produce txt file.
Example 1:
Best score for a1_score.txt: 5712
Best score for a2_score.txt: 14696
Example 2:
Best score for data\a1_score.txt: 3023
Best score for data\a2_score.txt: 451
Example 3:
Best score for D:\tmp\a1_score.txt: 234
Best score for D:\tmp\a2_score.txt: 1062
Strings are different because of including full file path. But, fortunately names of file ("a1_score.txt " and "a2_score.txt") will not be changed.
I need two numbers to call next tool, so I tried to write script … but I'm not familiar with the command language and examples I have found in the Internet are not so useful.
Please, help ne to complete the following code:
if exist scores.dat goto scores
echo Cannot read scores
goto BADEND
:scores
for /f "delims=" %%a in ('findstr /c:a1_score.txt /c:a2_score.txt "scores.dat"') do (
set str=%%a
:: some code to create a1_score and a2_score with corresponding values
)
echo %a1_score%
echo %a2_score%
:: some other code
goto END
:BADEND
echo Process was not completed due to errors
:END
pause
Next code snippet could help:
#ECHO OFF >NUL
SETLOCAL enableextensions enabledelayedexpansion
set "scores_dat=%~dp0files\scores32003340.dat" :: my filename value for debugging
if exist "%scores_dat%" goto scores
echo Cannot read scores
goto BADEND
:scores
for /f "tokens=1,2,* delims=:" %%a in ('
findstr /R "a[12]_score.txt" "%scores_dat%"
') do (
if "%%c"=="" (
set str=%%a
set /A "!str:~-12,8!=%%b"
) else (
set str=%%b
set /A "!str:~-12,8!=%%c"
)
)
set a|find /I "score"
echo(%a1_score%
echo(%a2_score%
:: some other code
goto END
:BADEND
echo Process was not completed due to errors
:END
Resources (required reading):
(command reference) An A-Z Index of the Windows CMD command line
(additional particularities) Windows CMD Shell Command Line Syntax
(%~G etc. special page) Command Line arguments (Parameters)
(special page) EnableDelayedExpansion
(for special page) FOR loop summary: all variants
Problem: The below batch program exits when trying to run the 1st for loop, and %file3% txt file only has:
Displayname
-------------
Need advice on why the for loop is not working please.
Partial output of REG query in 1st for loop in a text file:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Adobe AIR
DisplayName REG_SZ Adobe AIR
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Cisco AnyConnect Secure Mobility Client
DisplayName REG_SZ Cisco AnyConnect Secure Mobility Client
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\CitrixOnlinePluginPackWeb
DisplayName REG_SZ Citrix Receiver
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\KLiteCodecPack_is1
DisplayName REG_SZ K-Lite Codec Pack 10.7.5 Basic
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Mobile Broadband HL Service
DisplayName REG_SZ Mobile Broadband HL Service
Desired output in %file3%:
Displayname
-------------
Adobe AIR
Cisco AnyConnect Secure Mobility Client
Citrix Receiver
K-Lite Codec Pack 10.7.5 Basic
Mobile Broadband HL Service
Batch code:
#echo OFF
setlocal enableextensions enabledelayedexpansion
set "Version_tool=v2"
Echo Version: %Version_tool%
Echo Modified 19/01/15 by xxx
SET "ComputerName=%computername%"
echo ComputerName is: %ComputerName%
SET "file3=%~dp0%computername%-programs_unsorted.txt"
echo File3 is: %file3%
If Exist %file3% Del %file3%
echo Displayname >> %file3%
echo ------------- >> %file3%
set "keyname=HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
echo keyname is: !keyname!
Rem === Problem is below - program exits when running for loop ===
For /f "usebackq tokens=* delims=" %%A in (`REG Query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\" /V /F DisplayName /S /E`) do (
pause
set "DisplayName=%%A"
echo DisplayName is: !Displayname!
pause
set "Display_Substring=!DisplayName:~0,71!"
echo Display_Substring is: !Display_Substring!
pause
if not "!DisplayName:HKEY_LOCAL_MACHINE=!"=="!DisplayName!" echo !DisplayName! >> %file3%
::if !DisplayName:~0,71!==HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\ (
:: echo skipping !DisplayName!
::) else (
:: echo !DisplayName! >> %file3%
::)
)
Problems:
1) You specify usebackq, but you used single quotes, so FOR /F processes the string instead of the command. Drop the usebackq and the loop will process the command properly. The only time I ever use usebackq is when I am reading from a file whose path must be quoted, typically because of spaces.
2) Your IF statement is a mess:
Your command uses normal expansion instead of delayed expansion, so it cannot see the value set within the loop.
You used = but the comparison operator is ==.
Values should be quoted on both sides of the comparison when using delayed expansion substring operation within an IF statement, or you must escape the comma. I recommend the quotes (actually you don't even need the IF at all)
if "!DisplayName:~1,71!"=="yourValue..."
3) You want to exclude the summary line of output. The simplest solution is to pipe the output to FIND or FINDSTR and let it filter out lines you don't want. The pipe operator must be escaped within the IN() clause.
4) You can let FOR /F parse out the columns (tokens). You want the 3rd column, which contains spaces. None of the prior columns contain spaces, so you can use tokens=2*, which means capture the 2nd token in the first variable, and preserve everything after that in the second variable.
for /f "tokens=2*" %%A in (
'REG Query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" /V /F DisplayName /S /E^|find "DisplayName"'
) do echo %%B>>"%file3%"
Im writing a batch script to run on a flash drive. I need to validate the volume serial number of flash drive inside the code, therefore nobody should be able to run it from a different location.
Does anyone know how to validate serial number inside a batch file?
Example:
IF %VOL%==ABCD GOTO A ELSE EXIT
Although there are several different ways to achieve the same thing, the original DOS/Windows command intended to manage volumes and serial numbers is VOL:
#echo off
for /F "skip=1 tokens=5" %%a in ('vol %~D0') do set Serial=%%a
if %Serial% equ ABCD-EF01 do (
echo Valid serial number!
)
You can probably use WMIC and do something like:
wmic logicaldisk where drivetype=3 get volumeserialnumber
See parameter types in the link mentioned.
Edit:
#echo off
for /F "skip=1 delims=" %%j in ("wmic logicaldisk where deviceid = 'C:' get volumeserialnumber") do (
set SERIAL=%%j
goto :DONE
)
:DONE
echo SERIAL=%SERIAL%
if "%SERIAL%"=="BLAH" (
echo "Bluh"
)