I'm trying to make a .bat file that pings arbitrary hosts, but my options are not working. Maybe someone can help with this question
Why not scan all devices at once? You can do it in seconds
Create a file named Scan.bat
#echo off
if not "%1"=="am_admin" (powershell start -verb runas '%0' am_admin & exit /b)
arp -d
setlocal
setlocal enabledelayedexpansion
for /f "usebackq tokens=*" %%a in (`ipconfig ^| findstr /i "192"`) do (
for /f delims^=^:^ tokens^=2 %%b in ('echo %%a') do (
for /f "tokens=1-4 delims=." %%c in ("%%b") do (
set _o1=%%c
set _o2=%%d
set _o3=%%e
set _o4=%%f
set _3octet=!_o1:~1!.!_o2!.!_o3!.
for /L %%a in (1,1,254) do (start /min ping /n 1 /l 1 !_3octet!%%a)
)))
endlocal
Run the above file every time before typing the command below
arp -a | findstr 192 | findstr dynamic
You can then view all the devices connected to your network with this command
Related
Here is my batch file
#echo off
set /a IPCOUNT=1
set IP_FILTER=^IPV4
for /f "tokens=1,2,3 delims=:" %%i in ('2^>nul ipconfig | findstr /i "!IP_FILTER!" | findstr /v "%"') do (
if "%%j" NEQ " 127.0.0.1" (
echo !IPCOUNT! %%j
set IP_CHECK=%%j
echo !IP_CHECK!>>"%REGULAR_IP_FILE%"
set /a IPCOUNT+=1
)
)
When I run this code, I am getting the following error:
| was unexpected at this time.
How can I solve this?
The fixed code is as follows:
#echo off
setlocal EnableDelayedExpansion
set "IPcount=1"
set "IP_filter=IPV4"
for /F "tokens=2 delims=:" %%A in ('2^>nul ipconfig ^| findstr /IRC:"%IP_filter%"') do (
for /F "tokens=*" %%B IN ("%%A") do (
if not "%%B" == "127.0.0.1" (
echo !IPcount! %%B
(echo %%B)>>"%REGULAR_IP_FILE%"
set /a "IPcount+=1"
)
)
)
I have enabled delayed expansion. It seems you use it in your file, but you haven't enabled it.
It seems you want to find your IPv4 Address. I have modified your script to add a better way. Note that IPv4 (case-insensitive) is not in the start of the line. A space is in the start of the line, so I removed ^, but kept regex enabled.
Quote set variables and values: set /a "var=value".
I am attempting to create a basic script that runs and checks for basic system info but I want the output to be formatted so the results are on the same line and easily readable.
#Echo Off
systeminfo | findstr /B /C:"OS Name" /C:"OS Version"
wmic cpu get name, status
systeminfo | findstr /C:"Total Physical Memory"
#echo off & setlocal ENABLEDELAYEDEXPANSION
SET "volume=C:"
FOR /f "tokens=1*delims=:" %%i IN ('fsutil volume diskfree %volume%') DO (
SET "diskfree=!disktotal!"
SET "disktotal=!diskavail!"
SET "diskavail=%%j"
)
FOR /f "tokens=1,2" %%i IN ("%disktotal% %diskavail%") DO SET "disktotal=%%i"& SET "diskavail=%%j"
ECHO(Total Space: %disktotal:~0,-9% GB
ECHO(Available Space: %diskavail:~0,-9% GB
systeminfo | find "System Boot Time:"
systeminfo | find "System Type:"
Echo Antivirus: & wmic /node:localhost /namespace:\\root\SecurityCenter2 path AntiVirusProduct Get DisplayName | findstr /V /B /C:displayName || echo No Antivirus installed
The main example of this would be the wmic command placing the result on the next line rather than the same line.
Also any tips of better ways of scripting what I currently have would be appreciated.
#echo off
setlocal
for /f "tokens=1,* delims=:" %%A in ('systeminfo') do (
if "%%~A" == "OS Name" (
call :print "%%~A" %%B
) else if "%%~A" == "OS Version" (
call :print "%%~A" %%B
call :cpu
) else if "%%~A" == "Total Physical Memory" (
call :print "%%~A" %%B
call :fsutil C:
) else if "%%~A" == "System Boot Time" (
call :print "%%~A" %%B
) else if "%%~A" == "System Type" (
call :print "%%~A" %%B
)
)
:next
call :antivirus
pause
exit /b
:print
setlocal enabledelayedexpansion
set "name=%~1"
if not defined name exit /b
set "name=%~1 "
set "full=%*"
set "full=!full:,=!"
set "data="
set "skip1="
for %%A in (!full!) do (
if not defined skip1 (
set "skip1=defined"
) else if not defined data (
set "data=%%~A"
) else (
set "data=!data! %%~A"
)
)
echo !name:~,30!: !data!
exit /b
:antivirus
setlocal enabledelayedexpansion
set "antivirus="
for /f "tokens=*" %%A in ('
2^>nul wmic /node:localhost
/namespace:\\root\SecurityCenter2 path AntiVirusProduct
Get DisplayName /value
^| findstr /i /b /c:"DisplayName" ^|^| echo No Antivirus installed
') do set "antivirus=%%~A"
if /i "!antivirus:~,12!" == "DisplayName=" set "antivirus=!antivirus:~12!"
call :print Antivirus "!antivirus!"
exit /b
:cpu
for /f "tokens=1,* delims==" %%A in ('wmic cpu get name^, status /value') do (
call :print "%%~A" %%B
)
exit /b
:fsutil
setlocal enabledelayedexpansion
2>nul >nul net session || exit /b
for /f "tokens=1,* delims=:" %%A in ('2^>nul fsutil volume diskfree %1') do (
set "name=%%~A"
set "value=%%~B"
call :print "!name:bytes=GBs!" !value:~,-9!
)
exit /b
The fsutil command outputs alittle different.
I chose an easy option if it is OK.
Unsure of antivirus output as you need both results of
installed or not to be sure.
It only runs systeminfo once to save time.
Look at set /? for information about substitution that
is used.
The net session command is used to test if script is run as Admin.
If not Admin, then fsutil will be skipped as it requires Admin.
Look at for /? for usage of the command that is used in the script.
Use of enabledelayedexpansion is used to prevent special
characters being exposed which may cause error otherwise.
And used in code blocks to delay expansion as needed.
Remove comma from value strings which get replaced with a space.
A comma is often used as thousands separator and numbers look odd
with a space instead. This occurs because of usage of a simple
for loop interpreting comma as a argument separator. Some other
chararters may also do this though perhaps a space maybe better
than none in their case.
The output of WMIC is unicode !
The trailing <CR> can be removed by passing the value through another FOR /F loop. This also removes the phantom "blank" line (actually a <CR>)
#Echo Off
Call :GET_CPU name CPU_Name
Set "WMIC_Antivirus=wmic /node:localhost /namespace:\\root\SecurityCenter2 path AntiVirusProduct Get DisplayName ^| findstr /V /B /C:displayName"
#For /F "delims=" %%I in ('%WMIC_Antivirus%') do (
for /f "delims=" %%A IN ("%%I") DO SET "Antivirus=%%A"
)
echo CPU : %CPU_Name%
echo Antivirus : %Antivirus%
pause & exit
::----------------------------------------------------
:GET_CPU
Set "WMIC_CPU=wmic cpu get name /Value"
FOR /F "tokens=2 delims==" %%I IN (
'%WMIC_CPU% ^| find /I "%~1" 2^>^nul'
) DO FOR /F "delims=" %%A IN ("%%I") DO SET "%2=%%A"
Exit /b
::----------------------------------------------------
You can try to save the output into a text file :
#Echo Off
:::::::::::::::::::::::::::::::::::::::::
:: Automatically check & get admin rights
:::::::::::::::::::::::::::::::::::::::::
REM --> Check for permissions
Reg query "HKU\S-1-5-19\Environment" >nul 2>&1
REM --> If error flag set, we do not have admin.
if '%errorlevel%' NEQ '0' (
Echo.
ECHO **************************************
ECHO Running Admin shell... Please wait...
ECHO **************************************
goto UACPrompt
) else ( goto gotAdmin )
:UACPrompt
echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs"
set params = %*:"=""
echo UAC.ShellExecute "cmd.exe", "/c ""%~s0"" %params%", "", "runas", 1 >> "%temp%\getadmin.vbs"
"%temp%\getadmin.vbs"
del "%temp%\getadmin.vbs"
exit /B
:gotAdmin
::::::::::::::::::::::::::::
::START
::::::::::::::::::::::::::::
SetLocal EnableDelayedExpansion
set "Log=%~dp0Log.txt"
If exist "%Log%" Del "%Log%"
Call :GET_CPU name CPU_Name
Set "WMIC_Antivirus=wmic /node:localhost /namespace:\\root\SecurityCenter2 path AntiVirusProduct Get DisplayName ^| findstr /V /B /C:displayName"
#For /F "delims=" %%I in ('%WMIC_Antivirus%') do (
for /f "delims=" %%A IN ("%%I") DO SET "Antivirus=%%A"
)
(
Echo.
Echo ***************************** General infos ***********************************
Echo.
Echo Running under: %username% on profile: %userprofile%
Echo Computer name: %computername%
Echo.
systeminfo
Echo Operating System:
Echo PROCESSOR ARCHITECTURE : %PROCESSOR_ARCHITECTURE%
echo NUMBER_OF_PROCESSORS : %NUMBER_OF_PROCESSORS%
echo PROCESSOR_IDENTIFIER : %PROCESSOR_IDENTIFIER%
echo PROCESSOR_LEVEL : %PROCESSOR_LEVEL%
echo PROCESSOR_REVISION : %PROCESSOR_REVISION%
echo OS TYPE : %OS%
echo(
echo Program files path : %Programfiles%
echo Program files(86^) path : %Programfiles(86^)%
echo ProgramW6432 path : %ProgramW6432%
echo PSModulePath : %PSModulePath%
echo SystemRoot : %SystemRoot%
echo Temp Folder : %Temp%
echo CPU : !CPU_Name!
echo Antivirus : !Antivirus!
Echo.
Echo **************************** Drives infos *************************************
Echo.
Echo Listing currently attached drives:
wmic logicaldisk get caption,description,volumename | find /v ""
Echo.
Echo Physical drives information:
for /F "tokens=1-3" %%A in ('fltmc volumes^|find ":"') do echo %%A %%B %%C
)>>"%Log%"
Start "" "%Log%" & exit
::----------------------------------------------------
:GET_CPU
Set "WMIC_CPU=wmic cpu get name /Value"
FOR /F "tokens=2 delims==" %%I IN (
'%WMIC_CPU% ^| find /I "%~1" 2^>^nul'
) DO FOR /F "delims=" %%A IN ("%%I") DO SET "%2=%%A"
Exit /b
::----------------------------------------------------
I have recently started diving into writing Batch files and I have a question. I'm trying to create a file that checks to see if my secondary monitor is connected and than if it is switches the primary display to the secondary screen. (Yes I do know about the windows+P shortcut)...
So far I have figured out that "DisplaySwitch.exe /external" sets the default display to the secondary monitor but I cannot find out how to detect whether the display is there first.
-Cheers, Luke
With Windows 10, may be just a call to:
wmic desktopmonitor get DeviceID
output:
DeviceID
DesktopMonitor1
DesktopMonitor2
More details about monitor with :
wmic desktopmonitor get
By calling a powershell from the cmd the following will get the number of monitors:
powershell -Command "exit (Get-CimInstance -Namespace root\wmi -ClassName WmiMonitorBasicDisplayParams | Select-String -Pattern 'InstanceName').length"
set nMons=%ERRORLEVEL%
One possible way is to use dxdiag though it is not the fastest way:
#echo off
del ~.txt /q /f >nul 2>nul
dxdiag /t ~
w32tm /stripchart /computer:localhost /period:1 /dataonly /samples:3 >nul 2>&1
setlocal enableDelayedExpansion
set currmon=1
for /f "tokens=2 delims=:" %%a in ('find "Current Mode:" ~.txt') do (
echo Monitor !currmon! : %%a
set /a currmon=currmon+1
)
endlocal
del ~.txt /q /f >nul 2>nul
this will print the resolutions of all monitors.
Update:
dxdiag prints info about all monitors so you can check if there are more than one monitors:
#echo off
del ~.txt /q /f >nul 2>nul
start "" /w dxdiag /t ~
for /f "tokens=1* delims=:" %%a in ('find /c "Current Mode:" "~.txt"') do (
set /a "number_of_monitors=%%b"
rem echo #%%b#
)
rem exit /b 0
echo %number_of_monitors%
rem :---- if it needed -----:
if defined number_of_monitors ( if %number_of_monitors% GTR 1 ( echo second monitor connected ) else (echo only one monitor connected ))
del ~.txt /q /f >nul 2>nul
#npocmaka's answer didn't quite work for me, but this variation of his code did (Windows 10):
rem #echo off
del %TEMP%\dxdiag.txt /q /f >nul 2>nul
start "" /w dxdiag -64bit -t %TEMP%\dxdiag.txt
for /f "tokens=3" %%f in ('find /c"Monitor Name:" %TEMP%\dxdiag.txt') do set MONITOR_COUNT=%%f
if defined MONITOR_COUNT ( if %MONITOR_COUNT% GTR 1 ( echo second monitor connected ) else (echo only one monitor connected ))
del %TEMP%\monitors.txt /q /f >nul 2>nul
SET monitors=monitors.txt
SET nMons=0
MultiMonitorTool.exe /scomma "%monitors%"
FOR /F "skip=1 tokens=9 delims=," %%a IN (%monitors%) DO IF %%a GTR 0 SET /A nMons += 1
echo Number of monitors: %nMons%
MultiMonitorTool
Here is quick way to get connected monitors count via powershell
$m = Get-PnpDevice -Class Monitor -Status OK | measure; $m.Count
What I am trying to do, is speed up my reading results of batch file.
Am trying to get different values using netsh commands and then present them in my script console but it takes to long.
See below a small part of my script to get the idea. (this is just a small part, I'm actually getting around 50 different values and using more netsh commands)
Does anybody know a way to speed up the process?
.
.
.
netsh interface ipv4 show config %AdapterLAN% >temp
for /f "tokens=3" %%i in ('findstr "IP Address" temp') do set ip=%%i
echo. IP Address : %ip%
for /f "tokens=5 delims=) " %%i in ('findstr "Subnet Prefix" temp') do set mask=%%i
echo. Mask : %mask%
for /f "tokens=3" %%i in ('findstr "Gateway:" temp') do set gateway=%%i
echo. Gateway : %gateway%
for /f "tokens=1,5,6" %%a in ('findstr "DNS" temp') do set dns1=%%a&set dns5=%%b&set dns6=%%c
If "%dns1%"=="Statically" set dns=%dns5%
if "%dns1%"=="DNS" set dns=%dns6%
echo. DNS Server : %dns%
for /f "tokens=3" %%i in ('findstr "Gateway Metric" temp') do set GMetric=%%i
for /f "tokens=2" %%i in ('findstr "InterfaceMetric" temp') do set IMetric=%%i
set /a metricLAN=Gmetric + imetric
echo. Metric : %metricLAN%
for /f "tokens=3" %%i in ('find "DHCP enabled" temp') do set LANDHCP=%%i
If "%dns1%"=="Statically" set xx=Static
if "%dns1%"=="DNS" set xx=DHCP
If /i %LANDHCP%==No set LANDHCP=Static
if /i %LANDHCP%==YES set LANDHCP=DHCP
echo. Obtained IP : %LANDHCP%
echo. Obtained DNS : %xx%
for /f "tokens=3 delims=," %%a in ('getmac /v /fo csv ^| find """%AdapterLAN-without-Q%""" ') do set macLAN=%%a
echo. MAC-Addres : %macLAN%
del temp
.
.
.
netsh wlan show profile >temp
.
Do a similar process of getting values from another netsh command sent them
in the temp file …echo the one I want on the screen ..delete the file etc.
Next approach could be a bit faster (no temporary file(s), updated no multiple findstr):
#ECHO OFF >NUL
SETLOCAL enableextensions enabledelayedexpansion
set "AdapterLAN=wiredEthernet"
set "IMetric="
set "GMetric="
for /F "tokens=1,2* delims=:" %%G in ('
netsh interface ipv4 show config "%AdapterLAN%"^|findstr /N /R "^"
') do (
rem echo G="%%G" H="%%H" I="%%I"
if "%%I"=="" (
rem line 1 skip
rem line 2 = Configuration for interface
rem line 10 = DNS server #2 etc.
) else (
set "hh=%%H"
set "xx=!hh:IP Address=!"
if not "!hh!"=="!xx!" for /F "tokens=1*" %%i in ("%%I") do set "ip=%%i"
set "xx=!hh:Subnet Prefix=!"
if not "!hh!"=="!xx!" for /F "tokens=3 delims=) " %%i in ("%%I") do set "mask=%%i"
set "xx=!hh:Default Gateway=!"
if not "!hh!"=="!xx!" for /F "tokens=1*" %%i in ("%%I") do set "gateway=%%i"
set "xx=!hh:Gateway Metric=!"
if not "!hh!"=="!xx!" for /F "tokens=1*" %%i in ("%%I") do set "GMetric=%%i"
set "xx=!hh:InterfaceMetric=!"
if not "!hh!"=="!xx!" for /F "tokens=1*" %%i in ("%%I") do set "IMetric=%%i"
)
)
echo( IP Address : [%ip%]
echo( Mask : [%mask%]
echo( Gateway : [%gateway%]
set /a metricLAN=Gmetric + IMetric
echo( Metric : [%metricLAN%]
ENDLOCAL
goto :eof
Output:
==>D:\bat\SO\31356115.bat
IP Address : [192.168.1.100]
Mask : [255.255.255.0]
Gateway : [192.168.1.1]
Metric : [20]
==>
Edit
Here is another approach: unlike netsh, parsing the wmic command output seems to be a bit easier when used get verb together with /value switch as it's well defined and well structured. You could find here all the info as from netsh: next code snippet should read and make public a huge range of information about all enabled NIC adapter(s) in a defined local or remote computer:
#ECHO OFF >NUL
SETLOCAL enableextensions enabledelayedexpansion
set "NetCount=0"
set "compName=%computername%" :: local or remote computer name
set "compIDXs="
for /F "tokens=2 delims==" %%N in ('
wmic /node:"%compName%" NIC where "NetEnabled=TRUE" get InterfaceIndex /value 2^>NUL ^| find "="
') do for /F "tokens=*" %%n in ("%%N") do (
for /F "tokens=*" %%G in ('
wmic /node:"%compName%" NIC where "InterfaceIndex=%%n" get /value 2^>NUL ^| find "="
') do for /F "tokens=*" %%g in ("%%G") do set "_%%n%%g"
for /F "tokens=*" %%I in ('
wmic /node:"%compName%" NICCONFIG where "InterfaceIndex=%%n" get /value 2^>NUL ^| find "="
') do for /F "tokens=*" %%i in ("%%I") do set "_%%n_%%i"
set /A "NetCount+=1"
set "compIDXs=!compIDXs! "%%n""
)
set _
rem sample of it:
echo compName=%compName% NetCount=%NetCount% compIDXs=%compIDXs%
for %%x in (%compIDXs%) do (
echo enabled InterfaceIndex=%%~x NetConnectionID=!_%%~xNetConnectionID!
for /F "tokens=1,2 delims={}," %%i in ("!_%%~x_IPAddress!") do echo ipv4=%%~i ipv6=%%~j
)
Read Dave Benham's WMIC and FOR /F: A fix for the trailing <CR> problem to see why any wmic command output is parsed via a couple of nested for loops.
I currently have a batch file that reads a list of computer names and pings each of these and outputs the ones that reply to a csv file with the computer name and ip address.
I now need to edit this to also find out the user of the machine. I need to contact users which are online to arrange some work done to their computer. Their can be over a hundred machines in the batch file so to manually find out each user takes time. Is there a way to do this?
`IF EXIST C:\test\new.csv (del C:\test\new.csv)
IF EXIST C:\test\final.csv (del C:\test\final.csv)
set ComputerList=C:\test\ClientList.txt
Echo Computer Name,IP Address>Final.csv
setlocal enabledelayedexpansion
echo please wait...
for /f "usebackq tokens=*" %%A in ("%ComputerList%") do (
for /f "tokens=3" %%B in ('ping -n 1 -l 1 %%A ^|findstr Reply') do (
set IPadd=%%B
echo %%A,!IPadd:~0,-1!>>final.csv
)
)
findstr /V "IPAddress" final.csv >> C:\test\new.csv
echo identified machines for Install
start excel C:\test\new.csv
echo opened csv file`
The command I want to use to get the username is:
`wmic.exe /NODE: %%A COMPUTERSYSTEM GET USERNAME`
Thanks
Mark
Here is a function I wrote to do just what you are trying to do:
:GetLoggedInUser comp user
for /f %%u in (
'wmic /NODE:"%1" Computersystem get username^|find "\"') do (
if not errorlevel 1 ( for /f "tokens=2 delims=\" %%a in (
'wmic /NODE:"%1" Computersystem get username^|find "\"' ) do (
For /f %%b in ("%%a") do (set %2=%%b))
) ELSE (for /f "skip=1" %%a in (
'wmic /NODE:"%1" Computersystem get username' ) do (
For /f %%b in ("%%a") do (set %2=%%b))
))
Exit /b
Here is my function for pinging. It returns a 0 if the ping succeeded and a 1 otherwise.
:IsPingable comp
ping -n 1 -w 3000 -4 -l 8 "%~1" | Find "TTL=">nul
exit /b
Usage example:
for /l %%a in (1,1,255) do (
call:IsPingable 10.6.1.%%a && (
echo ping 10.6.1.%%a used )||( echo ping 10.6.1.%%a unused )
)
And here is for if you're pinging IP's and want to return the hostname as well:
:IsPingable2 comp ret
setlocal
for /f "tokens=2" %%a in (
'"ping -a -n 1 -4 "%~1" | Find "Pinging" 2>nul"') do set name=%%a
endlocal & set %~2=%name%
ping -n 1 -w 3000 -4 -l 8 "%~1" | Find "TTL=">nul
exit /b
Usage example:
#echo off
setlocal enabledelayedexpansion
for /l %%a in (1,1,255) do (
call:IsPingable2 10.6.1.%%a host && (
echo ping !host! - 10.6.1.%%a used )||( echo ping !host! - 10.6.1.%%a unused )
)
I just posted these because they just might come in handy for this type of thing in the future. You can use the :IsPingable now though.
You would use it like this in your code:
IF EXIST C:\test\final.csv (del C:\test\final.csv)
set ComputerList=C:\test\ClientList.txt
Echo Computer Name,IP Address,Logged In User>Final.csv
setlocal enabledelayedexpansion
echo please wait...
echo.
for /f "usebackq tokens=*" %%A in ("%ComputerList%") do (
for /f "tokens=3" %%B in ('ping -n 1 -l 1 %%A ^|find "TTL="') do (
if not errorlevel 1 (
set IPadd=%%B
call :GetLoggedInUser %%B uname
echo %%A,!IPadd:~0,-1!,!uname!>>final.csv
)
)
)
echo identified machines for Install
start excel C:\test\final.csv
echo opened csv file
goto :eof
:GetLoggedInUser comp user
for /f %%u in (
'wmic /NODE:"%1" Computersystem get username^|find "\"') do (
if not errorlevel 1 ( for /f "tokens=2 delims=\" %%a in (
'wmic /NODE:"%1" Computersystem get username^|find "\"' ) do (
For /f %%b in ("%%a") do (set %2=%%b))
) ELSE (for /f "skip=1" %%a in (
'wmic /NODE:"%1" Computersystem get username' ) do (
For /f %%b in ("%%a") do (set %2=%%b))
))
Exit /b
The below code will count the number of lines in two files sequentially and is set to the variables SalaryCount and TaxCount.
#ECHO OFF
echo Process started, please wait...
for /f %%C in ('Find /V /C "" ^< "D:\Trial\Salary.txt"') do set SalaryCount=%%C
echo Salary,%SalaryCount%
for /f %%C in ('Find /V /C "" ^< "D:\Trial\Tax.txt"') do set TaxCount=%%C
echo Tax,%TaxCount%
Now if you need to output these values to a csv file, you could use the below code.
#ECHO OFF
cd "D:\CSVOutputPath\"
echo Process started, please wait...
echo FILENAME,FILECOUNT> SUMMARY.csv
for /f %%C in ('Find /V /C "" ^< "D:\Trial\Salary.txt"') do set Count=%%C
echo Salary,%Count%>> SUMMARY.csv
for /f %%C in ('Find /V /C "" ^< "D:\Trial\Tax.txt"') do set Count=%%C
echo Tax,%Count%>> SUMMARY.csv
The > will overwrite the existing content of the file and the >> will append the new data to existing data. The CSV will be generated in D:\CSVOutputPath