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"
)
Related
Stack community good day! Thank you in advance for your time
I would like to create a bat file in order to autocreate an iso file from the DVD drive. So the logic will be:
Find which is the CD/DVD drive (from many drives)
And use that result as a variable (of the drive: for example F:) which will be executed in the following command:
cdbxpcmd.exe --burn-data -folder:F:\ -iso:C:\donalds.iso -format:iso
So in the previous command, the F:\ will be the variable, lets say %input%:\ which the program cdbxpcmd will use in order to create an iso from that drive.
I have found the following script that finds the drive letter,
from here: https://itectec.com/superuser/windows-how-to-detect-dvd-drive-letter-via-batch-file-in-ms-windows-7/
#echo off
setlocal
for /f "skip=1 tokens=1,2" %%i in ('wmic logicaldisk get caption^, drivetype') do (
if [%%j]==[5] echo %%i
)
endlocal
Do you believe that we could combine them? And how? Any suggestions?
You could use cdbxpcmd.exe itself to locate your drive:
Two line batch-file example:
#Set "CDBXP=C:\Program Files\CDBurnerXP\cdbxpcmd.exe"
#For /F "Tokens=2 Delims=()" %%G In ('^""%CDBXP%" --list-drives^"') Do #"%CDBXP%" --burn-data -folder:%%G -iso:"C:\donalds.iso" -format:iso
Just change the location where you have your cdbxpcmd.exe command line utility between the = and the closing " on line 1.
Alternatively, you could still use WMI, but personally, I would not use Win32_LogicalDisk, I would instead use Win32_CDROMDrive, which could verify both that a CDROM disk is loaded, and that it contains readable data.
Single line batch-file example:
#For /F Tokens^=6^ Delims^=^" %%G In ('%SystemRoot%\System32\wbem\WMIC.exe Path Win32_CDROMDrive Where "MediaLoaded='True' And DriveIntegrity='True'" Get Drive /Format:MOF 2^>NUL') Do #"C:\Program Files\CDBurnerXP\cdbxpcmd.exe" --burn-data -folder:%%G\ -iso:"C:\donalds.iso" -format:iso
Just change the location where you have your cdbxpcmd.exe command line utility, remembering to leave the doublequotes in place for best practice.
I have a .bat script where I need to compare my free disk space with exactly 18GB.
If it's lower or equal than 18GB, it should exit.
If It's greater, it should continue.
#echo off
setlocal
set maxSize=19327352832
for /f "tokens=3" %%a in ('dir c:\') do (
set bytesfree=%%a
)
set bytesfree=%bytesfree:,=%
Echo %bytesfree%
Echo %maxSize%
If %bytesfree% LEQ %maxSize% Echo You'll need to delete some stuff first & pause & exit
If %bytesfree% GTR %maxSize% Echo Everything ready
endlocal && set bytesfree=%bytesfree%
I have 5GB free on C:\, so it should say "Everything ready" but it says "You'll need to delete some stuff first" and I don't now what is wrong.
I'm very new to .bat so if I have unecessary code, please correct me.
Perhaps a wmic based batch-file would work for you:
#("%__AppDir__%wbem\WMIC.exe" LogicalDisk Where "DeviceID='C:' And FreeSpace>'18000000000'" Get FreeSpace /Value 2>NUL|"%__AppDir__%find.exe" "=">NUL&&(Echo Everything ready)||(Echo You'll need to delete some stuff first&"%__AppDir__%timeout.exe" /T 3 /NoBreak>NUL&Exit /B))&Pause
Change 18000000000 to 19327352832 as necessary.
Your problem is, that numbers in batch are limited to INT32 (that's about 2GB), so if returns unexpected results. As a workaround you can compare the numbers as strings (you need to make sure, they have the same number of digits). Note dir's switch /-c, which suprresses the thousand separators:
#echo off
setlocal
set "maxSize=0000019327352832"
for /f "tokens=3" %%a in ('dir /-c c:\') do (
set bytesfree=0000000000000000%%a
)
set bytesfree=%bytesfree:~-16%
Echo %bytesfree%
Echo %maxSize%
If "%bytesfree%" LEQ "%maxSize%" Echo You'll need to delete some stuff first & pause & exit
If "%bytesfree%" GTR "%maxSize%" Echo Everything ready
endlocal && set bytesfree=%bytesfree%
As an alternative, you could use the help of a "proper" programming language (like Powershell) for the math, but that's always slower and not really necessary here (as you can see)
I have been banging my head against the wall trying to figure this out. First, to answer what I'm sure will be asked, yes, I need to use a batch script. I'm sure that this is much easier in PowerShell or another language, but it needs to be a Windows Batch Script (CMD).
I am trying to re-design this script to be used on new systems and older systems within our company. The newer systems use Windows Server 2012, while the older systems use Windows Server 2008. Both systems will have 2 hard drives, but the difference between the 2 is the use of the second hard drive. On the older systems, the 2nd drive is used as a backup drive. On the newer system it is not.
In layman's terms, here is what I am looking to do:
IF ANY DISK VOLUME includes "Backup" in it's name (Caption)
SET %buletter% to the Drive Letter
SET other variables
ELSE
SET the backup location to something else
SET other variables
I've been able to pretty easily able to find how to find the name of the disk volume with the following:
FOR /f %%b IN ('wmic volume get DriveLetter^, Label ^| find "%lookfor%"') DO Stuff
But I haven't figured out how to wrap the FOR statement in an IF statement.
Any help is appreciated.
Thanks
Try this:
for /f "usebackq skip=1" %%p in (`wmic volume where "label like '%%Backup%%'" get Driveletter`) do echo Backup Drive is %%p
The only issue - it will give an empty string on a last iteration.
You don't have to use an IF initially,
you can use find and use conditional execution on success && or fail || or
initializing a var and using a for /f to eval the output - and afterwards check if the var is defined.
I'd exclude the first disk by checking for BootVolume in an extended where clause
:: Q:\Test\2019\01\25\SO_54366874.cmd
#Echo off
Set "BackUpDrive="
for /f "usebackq tokens=1,2*" %%A in (`
wmic volume where 'DriveType^="3" AND BootVolume^="FALSE" AND Label like "%%Backup%%"' get DriveLetter^,Label 2^>NUL ^| find ":"
`) Do Set "BackUpDrive=%%A"
If defined BackUpDrive (
Echo Drive with label Backup found: %BackUpDrive%
Rem other commands
) Else (
Echo no drive with label Backup found
Rem other commands
)
Sample output here:
> Q:\Test\2019\01\25\SO_54366874.cmd
Drive with label Backup found: D:
Using the idea from #mirGantrophy of checking the OS Version, this is what I came up with.
SET Version=
FOR /F "skip=1" %%v IN ('wmic os get version') DO IF NOT DEFINED Version set Version=%%v
FOR /F "delims=. tokens=1-3" %%a in ("%Version%") DO (
SET Version.Major=%%a
SET Version.Minor=%%b
SET Version.Build=%%c
)
IF %Version.Major% LSS 10 GOTO Win2008
IF %Version.Major%==10 GOTO Win2012
:Win2008
FOR /F %%p IN ('wmic logicaldisk where "VolumeName='%lookfor%'" get Caption ^| find ":"') DO (
SET buletter=%%p
SET bootdrvltr=C:
)
GOTO SetLocalDrv
:Win2012
SET buloc=C:\Archive
SET bootdrvltr=D:
GOTO SetLocalDrv
:SetLocalDrv
SET localdrv=%bootdrvltr%\Bootdrv
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
I do not have much experience with batch an d need a help with batch script.
Task is, return drive letter as parameter to %disk_letter%
Idea is use this for search:
WMIC LogicalDisk Where VolumeName='MY_USB' Get /Format:list | FIND "Caption="
I have "Caption=G:" as the result. I need that %disk_leter% parameter was equal just "G:"
Need help to finish this script.
Thank you!
On Linux right now but here's what I think you'll need to do. Part 1: save the result of your FIND command to a variable, and 2: take a substring of the variable. The second part is simple, so I'll start with that (assuming that in the first step you named your variable var
#echo %var:~-2%
That's about as far as I'm comfortable in batch, so this next bit is cobbled together:
To store the result of your find as a variable, try amending your code to:
set cmd="WMIC LogicalDisk Where VolumeName='MY_USB' Get /Format:list | FIND "Caption=" "
FOR /F %%i IN (' %cmd% ') DO SET var=%%i
and then (remember above) output it with:
#echo %var:~-2%
The related question from which I am cobbling together the second part is this question so if this doesn't work as expected I would jump over to that one first.
Here goes...
#echo off
for /F "usebackq tokens=1,2,3,4 " %%i in (`wmic logicaldisk get caption^,description^,drivetype
2^>NUL`) do (
if %%l equ 2 (
echo %%i is a USB drive.
)
)