101} How to capture Volume Serial Number into an environment variable?
@echo off & setlocal enableextensions
for /f "skip=1 tokens=5" %%s in ('vol c:') do set volc_=%%s
echo %volc_%
endlocal & goto :EOF
The output could be e.g.
C:\_D\TEST>cmdfaq
D634-E1B2
Why the skip=1? Do the "math". Because the output of VOL C: is
C:\_D\TEST>vol c:
Volume in drive C is MY_C
Volume Serial Number is D634-E1B2
The task of finding the Volume Serial Number can also be programmed as
a subroutine, including at the same time a slightly more advanced handling
@echo off & setlocal enableextensions
set dr_=C
if not "%~1"=="" set dr_=%~1
call :GetVolSerialNr %dr_% ser_
echo %ser_%
endlocal & goto :EOF
::
::===============================================================
:GetVolSerialNr
setlocal enableextensions
set return_=NoInfo
dir %~1: > "%temp%\tmp$$$.dir"
2>&1
find "The system cannot find the path specified" "%temp%\tmp$$$.dir" > nul
if %errorlevel% EQU 0
(set return_=DeviceNotFound
&goto _endGetVolSerialNr
)
dir %~1: > "%temp%\tmp$$$.dir" 2>&1
find "The device is not ready" "%temp%\tmp$$$.dir" > nul
if %errorlevel% EQU 0 (set return_=DeviceNotReady&goto _endGetVolSerialNr)
for /f "skip=1 tokens=5" %%s in ('vol %~1:') do set return_=%%s
:_endGetVolSerialNr
for %%f in ("%temp%\tmp$$$.dir") do if exist %%f del %%f
endlocal & set %2=%return_%&goto :EOF
The output could be e.g.
C:\_D\TEST>cmdfaq
D634-E1B2
or
C:\_D\TEST>cmdfaq E
DeviceNotFound
or
C:\_D\TEST>cmdfaq N
DeviceNotReady
It might be instructive to also have a Visual Basic Script solution.
First, the volume name:
@echo off & setlocal enableextensions
::
:: Build a Visual Basic Script
set vbs_=%temp%\tmp$$$.vbs
set skip=
findstr "'%skip%VBS" "%~f0" > "%vbs_%"
::
:: Run the VBS script with Microsoft Windows Script Host Version 5.6
for /f "delims=" %%a in ('cscript //nologo "%vbs_%" "
%CD%"') do (
set s_=%%a)
::
:: Display the result
echo %s_%
::
:: Clean up
for %%f in ("%vbs_%") do if exist %%f del %%f
endlocal & goto :EOF
'
'................................................................
'The Visual Basic Script
'
Set arg = WScript.Arguments 'VBS
Wscript.Echo ShowVolumeInfo(arg(0)) 'VBS
'
Function ShowVolumeInfo(drvpath) 'VBS from the Windows Script Documentation
Dim fso, d, s 'VBS
Set fso = CreateObject("Scripting.FileSystemObject") 'VBS
Set d = fso.GetDrive(fso.GetDriveName(fso.GetAbsolutePathName(drvpath))) 'VBS
s = "Drive " & d.DriveLetter & ": - " & d.VolumeName 'VBS
ShowVolumeInfo = s 'VBS
End Function 'VBS
The output might be e.g.
C:\_D\TEST>cmdfaq
Drive C: - MYCDRIVE
GetAbsolutePathName: Returns a complete and unambiguous path from a
provided path specification.
GetDriveName: Returns a string containing the name of the drive for a
specified path.
GetDrive: Returns a Drive object corresponding to the drive in a
specified path.
Likewise:
@echo off & setlocal enableextensions
::
:: Build a Visual Basic Script
set vbs_=%temp%\tmp$$$.vbs
set skip=
findstr "'%skip%VBS" "%~f0" > "%vbs_%"
::
:: Run the VBS script with Microsoft Windows Script Host Version 5.6
for /f "delims=" %%a in ('cscript //nologo "%vbs_%" "%CD%"') do (
set s_=%%a)
::
:: Display the result
echo %s_%
::
:: Clean up
for %%f in ("%vbs_%") do if exist %%f del %%f
endlocal & goto :EOF
'
'................................................................
'The Visual Basic Script
'
Set arg = WScript.Arguments 'VBS
Wscript.Echo ShowDriveInfo(arg(0)) 'VBS
'
Function ShowDriveInfo(drvpath) 'VBS
Dim fso, d, s, t 'VBS
Set fso = CreateObject("Scripting.FileSystemObject") 'VBS
Set d = fso.GetDrive(fso.GetDriveName(fso.GetAbsolutePathName(drvpath))) 'VBS
Select Case d.DriveType 'VBS
Case 0: t = "Unknown" 'VBS
Case 1: t = "Removable" 'VBS
Case 2: t = "Fixed" 'VBS
Case 3: t = "Network" 'VBS
Case 4: t = "CD-ROM" 'VBS
Case 5: t = "RAM Disk" 'VBS
End Select 'VBS
s = "Drive " & d.DriveLetter & ": - " & t 'VBS
s = s & ", SN: " & Left(Hex(d.SerialNumber),4) 'VBS
s = s & "-" & Right(Hex(d.SerialNumber),4) 'VBS
ShowDriveInfo = s 'VBS
End Function 'VBS
C:\_D\TEST>cmdfaq
Drive C: - Fixed, SN: D634-E1B2
You can also get the
label of a volume in a very similar manner:
@echo off & setlocal enableextensions
set target_=C:\
for /f "tokens=
5*" %%
f in (
'dir %target_%
^|find "Volume in drive "') do (
set label_=%%
g)
echo The label of Volume %target_% is %label_%
endlocal & goto :EOF
C:\_D\TEST>cmdfaq
The label of Volume C:\ is MYCDRIVE
Explanation of the
5*,
%%f and
%%g.
Obviously, the label is the sixth token. But one has to take into
account the eventuality that there might be a space in the label. If
one just used
6,
%%f and
%%f
the only the first part of such a label would be included. The
5*,
%%f
and
%%g formulation gets into
%%g everything that comes after the fifth
token, which is exactly what we want.
Programmed as a subroutine we have
@echo off & setlocal enableextensions
set target_=D:
::
call :IsDeviceReady %target_% isready_
echo Device %target_% ready: %isready_%
if /i "%isready_%"=="false" (endlocal & goto :EOF)
::
call :GetLabel %target_% label_
echo The label of Volume %target_% is %label_%
endlocal & goto :EOF
::
:IsDeviceReady
setlocal
set ready_=true
dir "%~1" > nul 2>&1
if %errorlevel% NEQ 0 set ready_=false
endlocal & set "%2=%ready_%" & goto :EOF
::
:GetLabel
setlocal
for /f "tokens=5*" %%a in (
'vol "%~1"^|find "Volume in drive "') do (
set label_=%%b)
endlocal & set "%2=%label_%" & goto :EOF
The subroutine can also be written without the
find as
:GetLabel
setlocal
for /f "tokens=5*" %%a in (
'vol "%~1"') do (
set label_=%%b& goto _ExitGetLabel)
:_ExitGetLabel
endlocal & set "%2=%label_%" & goto :EOF