Reporting Computer descriptions or not using WMIC - windows

I am making a script detect for presence of certain programs on a list of PC's and then report back the hostname, software list and the description for easier locating.
Everything is fine but I'm having trouble tidying up the output when "no" description is found. Where as before I would get the info needed in a tidy list, when there is no description, it just reports ECHO is on. 'or' ECHO is off.
here is my code
title Problem Software Itinary
echo.
echo List of PC Names goes here Plugins\hostnames.txt
echo.
echo Press a key to start...
pause>nul
CLS
echo.
break>Plugins\Logs\Results.txt
for /f "usebackq tokens=*" %%A in (Plugins\hostnames.txt) do (
echo ============================================= & echo =============================================>>Plugins\Logs\Results.txt
echo Scanning PC %%A... 2>&1 | Plugins\tee -a Plugins\Logs\Results.txt
if exist "\\%%A\C$\FOO" echo FOO PROG Installed 2>&1 | Plugins\tee -a Plugins\Logs\Results.txt
if exist "\\%%A\C$\FOO2" echo FOO 2 PROG Installed 2>&1 | Plugins\tee -a Plugins\Logs\Results.txt
for /f "tokens=2 Delims==" %%B in ('WMIC /NODE:"%%A" os get description /VALUE ^| find "Description"') Do Echo %%B 2>&1 | Plugins\tee -a Plugins\Logs\Results.txt
echo ============================================= & echo =============================================>>Plugins\Logs\Results.txt
)
start "" Plugins\Logs\Results.txt
echo.
echo Done! Press any key to return to Menu...
pause>nul
goto :audit
Here is example of it working and the echo problem:-
=============================================
=============================================
Scanning PC TESTPC1...
FOO PROG Installed
GP-B82047-ROOM 4
=============================================
=============================================
Scanning PC TESTPC2...
FOO 2 PROG Installed
ECHO is on.
=============================================
=============================================
I would prefer to have something echo back like "No Description Found"
to cure it I have tried setting a desc variable to %%B (set desc=%%b) (in the wmic line) (instead of Do Echo %%B) and then if defined desc (echo desc) ELSE (echo no description available). However that doesnt work either, same issue. Also I tried with delayed expansions enabled and no luck there.
What am I missing - thanks !!?

You actually have part of the solution in your script already, or at least one possible solution:
for /f "tokens=2 Delims==" %%B in ('WMIC /NODE:"%%A" os get description /VALUE ^| find "Description"') Do Echo %%B 2>&1 | Plugins\tee -a Plugins\Logs\Results.txt
If this echo could be empty, just change it to
for /f "tokens=2 Delims==" %%B in ('WMIC /NODE:"%%A" os get description /VALUE ^| find "Description"') Do Echo.%%B 2>&1 | Plugins\tee -a Plugins\Logs\Results.txt
Note the . after the echo. That'll suppress the error message from echo.
Also, note, it's generally better to use some character other than . for this, since if you have the misfortune of running on a machine with a program named echo in the path, the results can be unpredictable. : works well for this, so:
for /f "tokens=2 Delims==" %%B in ('WMIC /NODE:"%%A" os get description /VALUE ^| find "Description"') Do Echo:%%B 2>&1 | Plugins\tee -a Plugins\Logs\Results.txt
Will accomplish the same goal.

Related

filter out text inside loop in batch file

I am trying to process the output of wmic command in for loop:
#echo off
FOR /F "tokens=*" %%a in ('wmic process where "commandline like '%%w3wp.exe%%SharePoint%%-h%%config%%'" get commandline /VALUE /format:value') do (
echo %%a
)
It prints the following:
ECHO is off.
ECHO is off.
CommandLine=c:\windows\system32\inetsrv\w3wp.exe -ap "SharePoint Central Administration v4" -v "v4.0" -l "webengine4.dll" -a \\.\pipe\iisipm8d1b7d9b-4aee-49b5-87f0-1f5e78228544 -h "C:\inetpub\temp\apppools\SharePoint Central Administration v4\SharePoint Central Administration v4.config" -w "" -m 0
ECHO is off.
ECHO is off.
CommandLine=C:\Windows\system32\cmd.exe /c wmic process where "commandline like '%w3wp.exe%SharePoint%-h%config%'" get commandline /VALUE /format:value
ECHO is off.
ECHO is off.
CommandLine=wmic process where "commandline like '%w3wp.exe%SharePoint%-h%config%'" get commandline /VALUE /format:value
ECHO is off.
ECHO is off.
ECHO is off.
What I am trying to do is to process only:
CommandLine=c:\windows\system32\inetsrv\w3wp.exe -ap "SharePoint Central Administration v4" -v "v4.0" -l "webengine4.dll" -a \\.\pipe\iisipm8d1b7d9b-4aee-49b5-87f0-1f5e78228544 -h "C:\inetpub\temp\apppools\SharePoint Central Administration v4\SharePoint Central Administration v4.config" -w "" -m 0
It seems that the following works:
#echo off
FOR /F "tokens=* skip=2" %%a in ('wmic process where "commandline like '%%w3wp.exe%%SharePoint%%-h%%config%%'" get commandline /VALUE /format:value') do (
SET OUTPUT=%%a & goto :next
)
:next
echo %OUTPUT%
#rem CommandLine=c:\windows\system32\inetsrv\w3wp.exe -ap "SharePoint Central Administration v4" -v "v4.0" -l "webengine4.dll" -a \\.\pipe\iisipm8d1b7d9b-4aee-49b5-87f0-1f5e78228544 -h "C:\inetpub\temp\apppools\SharePoint Central Administration v4\SharePoint Central Administration v4.config" -w "" -m 0
But it seems that skip=2 part depends on the wmic output format.
Is it possible to get the desired string without the skip=2 part?
I tried this, but this doesn't work(not sure I understand why):
#echo off
setlocal EnableDelayedExpansion
set "substring=SharePoint"
FOR /F "tokens=*" %%a in ('wmic process where "commandline like '%%w3wp.exe%%SharePoint%%-h%%config%%'" get commandline /VALUE /format:value') do (
set "string=%%a"
if "!string:%substring%=!"=="!string!" (
echo(!string!
goto :next
)
)
:next
endlocal
In your particular example above, you'd need ensure that you isolate only the process you're after, and not capture also the command lines you're using in the batch file too.
You could do that, by including a NOT LIKE filter:
#Echo Off
SetLocal EnableExtensions
For /F "Tokens=1,* Delims==" %%G In ('
%SystemRoot%\System32\wbem\WMIC.exe Process Where
"CommandLine Like '%%w3wp.exe%%SharePoint%%-h%%config%%' And Not CommandLine Like '%%WMIC.exe%%'"
Get CommandLine /Format:List 2^>NUL') Do For /F "Tokens=*" %%I In ("%%H"
) Do Echo %%I
Pause
Alternatively, (and IMO better based upon your provided output), filter first by the known NAME of the executable:
#Echo Off
SetLocal EnableExtensions
For /F "Tokens=1,* Delims==" %%G In ('
%SystemRoot%\System32\wbem\WMIC.exe Process Where
"Name = 'w3wp.exe' And CommandLine Like '%%w3wp.exe%%SharePoint%%-h%%config%%'"
Get CommandLine /Format:List 2^>NUL') Do For /F "Tokens=*" %%I In ("%%H"
) Do Echo %%I
Pause
WMIC is outputting extra sets of CRLF. That is why you see the ECHO is OFF error. So just pipe the WMIC command to findstr to get just the output you want.
FOR /F "tokens=*" %%a in ('wmic process where "commandline like '%%w3wp.exe%%SharePoint%%-h%%config%%'" get commandline /VALUE /format:value ^|findstr /B /I "CommandLine=') do (
echo %%a
)

"The process tried to write to a nonexistent pipe." bat file

I can run on command line this loop:
for /f "tokens=2" %i in ('arp -a ^| Find/i "dynamic"') do echo %i
but if I run the same bat file I get:
^C^C^C^Cthe process tried to write to a nonexistent pipe^C^C^C^C^C^C^C^C^
C:\1\test.bat:
for /f "tokens=2" %%i in ('arp -a ^ |Find/i "dynamic"') do echo %%i
Returned by your arp -a command:
C:\Users\test>arp -a
Interface: xxx.xx.xxx.40 --- 0xbe
Internet Address Physical Address
xxx.xx.xxx.18 xx-xx-xx-xx-xx-xx dynamic
xxx.xx.xxx.26 xx-xx-xx-xx-xx-xx dynamic
xxx.xx.xxx.34 xx-xx-xx-xx-xx-xx dynamic
xxx.xx.xxx.114 xx-xx-xx-xx-xx-xx dynamic
thanks for any help //Simon
You've introduced an additional whitespace character before the pipe, |. The caret, ^, therefore has the effect of escaping the whitespace and the pipe isn't escaped as it should be.
#For /F "Tokens=2" %%i In ('arp -a ^| Find /I "dynamic"') Do #(Echo %%i)>>"%~dp0output.txt"
to add the computername (when I interpret your comment correct):
#echo off
for /f "tokens=1,2" %%a in ('arp -a^|find "dynam"') do (
for /f "tokens=5" %%c in ('ping -a -n 1 %%a^|find "["') do (
>>"%~dp0output.txt" echo %%a %%b %%c
)
)
shows IP-address, MAC-address, Computer-name. Adapt the echo line to your needs.
You may have to adapt the tokens (tokens=5) (inner for) for your language.
You may want to add delims=. to the inner for to get the computer name only.
according to your comments:
#echo off
setlocal EnableDelayedExpansion
set number=0
for /f "tokens=1,2" %%a in ('arp -a^|find "dynam"') do (
set /a number +=1
for /f "tokens=5" %%c in ('ping -a -n 1 %%a^|find "["') do (
>>"%~dp0output.txt" echo %%b Computer!number!
)
)
Output:
00-24-fe-xx-xx-xx Computer1
f4-f5-e8-xx-xx-xx Computer2
48-d6-d5-xx-xx-xx Computer3
d4-85-64-xx-xx-xx Computer4
80-86-f2-xx-xx-xx Computer5
24-77-03-xx-xx-xx Computer6
fc-db-b3-xx-xx-xx Computer7
80-1f-02-xx-xx-xx Computer8
I've received this error repeatedly when accidentally piping a batch script to MSYS grep when I really meant to grep a file afterward:
> call foo.cmd | grep pattern path\to\file
The process tried to write to a nonexistent pipe.
The process tried to write to a nonexistent pipe.
The process tried to write to a nonexistent pipe.
The process tried to write to a nonexistent pipe.
...
I haven't been able to identify exactly what foo.cmd needs to do to result in this error (my foo.cmd is pretty long and complicated), but I figured I'd add this here anyway. Hopefully it helps someone (even myself in a few months). What I meant to say was:
> call foo.cmd && grep pattern path\to\file

Windows Batch - How to get the external IP into a batch-file variable

I am making a program that checks if a user's IP is a certain IP address.
Currently, I created a successful internal IP version:
#echo off
set userIp=192.168.90.100
for /f "tokens=4 delims= " %%i in ('route print ^| find " 0.0.0.0"') do set localIp=%%i
for /f "delims=[] tokens=2" %%a in ('ping %computername% -4 -n 1 ^| findstr "["') do set thisip=%%a
goto :Check
:Check
if %localIp%==%userIp% goto :Good
if %thisip%==%userIp% goto :Good
goto :Bad
And I am trying to make the same thing that works with external IPs.
I researched online, and here is what I got so far.
#echo off
for /f "tokens=2 delims=:" %%a IN ('nslookup myip.opendns.com. resolver1.opendns.com ^| findstr /IC:"Address"') do if /i %%a=="10.11.12.13" goto :Good
goto :Bad
I need a bit of help on how to fix this.
With pure batch/already present tools:
EDIT: changed the batch to properly handle also IPv6 addresses
#Echo off
for /f "tokens=1* delims=: " %%A in (
'nslookup myip.opendns.com. resolver1.opendns.com 2^>NUL^|find "Address:"'
) Do set ExtIP=%%B
Echo External IP is : %ExtIP%
Reference
Another one with powershell:
#Echo off
For /f %%A in (
'powershell -command "(Invoke-Webrequest "http://api.ipify.org").content"'
) Do Set ExtIP=%%A
Echo External IP is : %ExtIP%
And another slightly different powershell variant:
#Echo off
For /f %%A in (
'powershell -nop -c "(Invoke-RestMethod http://ipinfo.io/json).IP"'
) Do Set ExtIP=%%A
Echo External IP is : %ExtIP%
To get your public IP without additional parsing do this:
curl "http://api.ipify.org"
EDIT:
This version is more reliable across windows language versions:
for /f "tokens=3 delims== " %%A in ('
nslookup -debug myip.opendns.com. resolver1.opendns.com 2^>NUL^|findstr /C:"internet address"
') do set "ext_ip=%%A"
First it seems there is a . too much after the first .com.
Second when using your command with simply google.com and echo %a I get the following:
" xx.xx.xx.x" without the quotes and with two leading spaces!
So your if will never be true!
Change it to something like this: if "%%a"==" xx.xx.xx.x" Goto:good and you should be fine.

Windows Batch Check Hostname Exists

I want to check if a hostname exists on my PC (ie found in hosts file under C:\Windows\System32\drivers\etc).
Is there a way to find if it exist using a batch command or some other way?
Give a try for this batch file with some extra info :
#echo off
set "SearchString=localhost"
set "LogFile=%userprofile%\Desktop\LogFile.txt"
set "hostspath=%windir%\System32\drivers\etc\hosts"
(
Echo **************************** General info ****************************
Echo Running under: %username% on profile: %userprofile%
Echo Computer name: %computername%
Echo Operating System:
wmic os get caption | findstr /v /r /c:"^$" /c:"^Caption"
Echo Boot Mode:
wmic COMPUTERSYSTEM GET BootupState | find "boot"
Echo Antivirus software installed:
wmic /Node:localhost /Namespace:\\root\SecurityCenter2 Path AntiVirusProduct Get displayName | findstr /v /r /c:"^$" /c:"displayName"
Echo Executed on: %date% # %time%
Echo ********************* Hosts' File Contents with the string "%SearchString%" ************************
)>"%LogFile%"
for /f "delims=" %%a in ('Type "%hostspath%" ^| find /I "%SearchString%"') Do (
echo %%a >> "%LogFile%"
)
Start "" "%LogFile%"
Easier and more robust solution
url.bat:
#echo off
set url=%1
ping -n 1 %url% > nul 2> nul
if "%errorlevel%"=="0" (
echo %url% exists
) else (
echo %url% does not exist
)
Test
> url.bat google.com
google.com exists
> url.bat google.commmmmm
google.commmmmm does not exist
What you possibly can do is pinging the hostname you are looking for and then check for certain strings, that will show you if the hostname could be found or not. Would look like this (I guess):
#echo off
setlocal EnableDelayedExpansion
set /p input= "Hostname"
set hostexists=yes
For /f "tokens=1,2" %%a in ('ping -n 1 !input!') do (
if "x%%a"=="xFOO" if "x%%b"=="xBAR" set hostexists=no
)
If "x!hostexists!"=="xno" (
echo. "Does not exist"
) ELSE (
echo. "Does exist"
Pause
Basic thought is that when you try to ping a hostname that is not available, you will get a specific output from the commandline. Try it yourself: Open the cmd.exe (Hit the Windows-Button +R and type cmd) and in the commandline write ping foobar and wait a bit. You should get a message like: Ping-Request could not find "foobar" [...]. You take the first two words and put them into the code: 1st word to FOO and 2nd to BAR.
The program will look into the output of the ping command and place the first two words (=tokens) in %%a and %%b checking if they are equal to the desired words, marking the host does not exist.
I hope this will help :) Not sure if that is what you wanted :D
Greetings
geisterfurz007

Batch ping a list of computer names and write the results to file

The code below will write the computer name and ip address to file, but I would like it to also write the name of the computers it cannot ping with a fail next to it. I have no idea how I would modify the batch file to do this.
#echo off
Echo Pinging list...
set ComputerList=list.txt
Echo Computername,IP Address>Final.csv
setlocal enabledelayedexpansion
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!>>Results.csv
))
pause
You could use errorlevel set by findstr to substitute return string(s) if 'Reply' is not found:
('ping -n 1 -l 1 %%A ^|findstr Reply ^|^| echo Not found Failed:')
where || (escaped here because of for context with ^) means execute only if previous command failed.
As a side note, you should be aware that ping messages are system language dependent (they are translated to language of OS) so 'Reply' as success indicator works only for English versions.
This may not be directly what you are looking for, but I had a similar task: run ping and report success or failure. I'll leave extracting the IP address to you - seeing as you have already done it.
The problem with ping is that it returns success upon name resolution, whether packets get lost or host is unreachable (will report 0% Loss) is irrelevant.
FOR %%a IN (
google.com
a.b.c.d
) DO #FOR /F "delims=" %%p IN (
'PING -w 100 -n 1 %%a ^| findstr ^"Reply Request fail name^"'
) DO #(
ECHO "%%p" | FINDSTR TTL >2 && echo %%a, success, %%p || echo %%a, failed, %%p
) >> Results.csv
Logic: Ping once, filter only lines with the one of the words listed. If TTL exists in resulting line (output to STDERR or NUL to avoid output pollution) echo success, else echo failed.
I'm on English Windows, words will have to be adjusted for other languages.
EDIT:
FOR %%a IN (
google.com
a.b.c.d
) DO #FOR /F "delims=" %%p IN ('PING -n 1 %%a ^| findstr TTL ^|^| echo Failed') DO #(
ECHO "%%p" | FINDSTR TTL >2 && (for /f "tokens=3" %%b IN ("%%p") do #echo %%a, %%b) || echo %%a, failed, %%p
)
Less dependant on language, works only for IPv4, added IP extraction.
Filter ping output for TTL, set output to "Failed" if TTL not found.
If output string contains TTL, extract IP and echo host and IP, else echo host name and output string.

Resources