Batch scripting, mutlple finds and multple do sets - windows

At the moment I am running the following to get some information from 'systeminfo', however it needs to run systeminfo twice which takes some time. How would I be able to do multple 'Find"XXX" do sets'?
For /f "delims=" %%A IN ('systeminfo ^| Find "OS Name"') DO Set "VarA=%%A"
For /f "delims=" %%A IN ('systeminfo ^| Find "BIOS Version"') DO Set "VarB=%%A"
Any help is greatly appreciated.

Next code snippet could work (note set commands are merely ECHOed for debugging purposes; remove capitalized ECHO no sooner than debugged):
For /f "delims=" %%A IN ('systeminfo') DO (
For /F "delims=" %%G IN ('echo %%A ^| Find /I "OS Name"') Do ECHO Set "VarA=%%A"
For /F "delims=" %%G IN ('echo %%A ^| Find /I "BIOS Version"') DO ECHO Set "VarB=%%A"
)
However, follow Stephan's advice and parse wmic output rather (do not forget /value option). To do that correctly, note great Dave Benham's article WMIC and FOR /F: A fix for the trailing <CR> problem

I too would use WMIC, but there is a simple solution if you want to use SYSTEMINFO - use FINDSTR with two /C:"search strings"
for /f "tokens=1,2*" %A in ('systeminfo ^| findstr /c:"OS Name" /c:"BIOS Version"') do set "%A=%C"
The above will define two variables on an English machine: OS and BIOS.

Thanks for the replies guys.
I wanted to set the bit version windows the batch file would run on, I figured it out ages ago but thought I would post it here for those that came across it:
echo %PROCESSOR_ARCHITECTURE% | find "64" > NUL
If %ERRORLEVEL% equ 0 (Set bit=64) else (Set bit=32)
Thanks!

Related

Command output set as variable

I've been trying to make a script that installs the current nvidia driver, I've gone pretty far but there's one thing missing
I'm trying to use nvidia-smi to find the driver version and here's the command output
C:\>nvidia-smi --query-gpu=driver_version --format=csv
driver_version
457.30
I've been trying to set 457.30 in %driver% here's what I got so far
FOR /F "tokens=* skip=1" %%g IN ('nvidia-smi --query-gpu=driver_version --format=csv') do (SET "driver=%%g")
I also tried a combination with findstr but that ended up being a disaster
for /F "tokens=* skip=1" %%g in ('nvidia-smi --query-gpu=driver_version --format=csv ^| findstr "."') do set driver=%%g
In any case, %%g and %driver% return as empty.
echo %driver%
returns
C:\>echo
ECHO is on.
Any ideas?
Thank you for your cooperation.
Your variable isn't getting set because right now your nvidia-smi command is throwing an error (to stdout, curiously) but skip=1 is skipping over it so there's nothing left to set the variable to.
= is one of the default delimiters for strings and so both of the = symbols in your command need to be escaped for your query to be executed correctly.
#echo off
for /F "delims=" %%g IN ('nvidia-smi --query-gpu^=driver_version --format^=csv ^| find "."') do set "driver=%%g"
echo %driver%

Issues when getting a list of user profiles using WMIC

I was using the following batch command to retrieve all local user profiles (including domain users too) :
for /f "delims=" %%I in ('dir /a:d-h /b "%SystemDrive%\Users\*" 2^>nul ^| %SystemRoot%\System32\findstr.exe /i /l /x /v /g:"%bin%\exclude_users.txt"') do (
The problem is that this command has its limits: it doesn't really check if the users in question do actually have an account.
The user Compo provided me a methodology for retrieving the profile names, using WMIC.
So I ended up writing the following command:
#For /F "tokens=* skip=1" %%I In ('%__AppDir__%wbem\WMIC.exe UserAccount Get Name ^|%__AppDir__%findstr.exe /i /l /x /v /g:"%bin%\exclude_users.txt"') do (
The problem is: it ignores my exclusion file (which contains one user per line) and it ends up a profile without any name.
Any idea How I can solve these issues ?
#echo off
setlocal
set "bin=%~dp0"
for /f "tokens=* skip=1" %%I in ('
%__AppDir__%wbem\WMIC.exe UserAccount where Disabled^="FALSE" get Name ^|
%__AppDir__%WindowsPowerShell\v1.0\powershell -noprofile -command "$input.trim()" ^|
%__AppDir__%findstr.exe /i /l /x /v /g:"%bin%\exclude_users.txt"
') do echo "%%~I"
The wmic output is piped to powershell to be trimmed and then piped to findstr.
The wmic command will exclude disabled accounts by use of the where clause.
Change the setting of bin as needed.
If you want a solution which still uses WMIC, and your exclusion list, then the following should do as you require.
#For /F Tokens^=4Delims^=^" %%G In ('%__AppDir__%wbem\WMIC.exe UserAccount Where "LocalAccount='TRUE'" Assoc:List /ResultRole:Name 2^>NUL')Do #Echo %%G|%__AppDir__%findstr.exe /VXLIG:"%~dp0exclude_users.txt"
You can split that over multiple lines for easier reading too:
#For /F Tokens^=4Delims^=^" %%G In ('%__AppDir__%wbem\WMIC.exe UserAccount^
Where "LocalAccount='TRUE'" Assoc:List /ResultRole:Name 2^>NUL'
)Do #Echo %%G|%__AppDir__%findstr.exe /VXLIG:"%~dp0exclude_users.txt"

Quoting a long filenamed command in a for loop in a batch file

Linked:
Best free resource for learning advanced batch-file usage?
Dealing with quotes in Windows batch scripts
This appears to be one of those maddening quoting issues. In this example program:
#echo off
set wmicpath=%windir%\System32\wbem\wmic.exe
for /f "usebackq" %%a in (`%wmicpath% COMPUTERSYSTEM GET SystemType ^| findstr /I "x64"`) do (
echo %%a
)
The program runs just fine. Unless you try to quote the wmicpath. Imagine if you will that it contains a long path name. Then you should quote it. But I cannot quite get it to work. This fails:
for /f "usebackq" %%a in (`"%wmicpath%" COMPUTERSYSTEM GET SystemType ^| findstr /I "x64"`) do (
but this works!:
for /f "usebackq" %%a in (`"%wmicpath%" COMPUTERSYSTEM GET SystemType ^| findstr /I x64`) do (
as does this:
for /f "usebackq" %%a in (`"%wmicpath%" COMPUTERSYSTEM GET SystemType`) do (
There's something really odd about matching quotes in a for command. You can quote a command as long as you don't start quoting elsewhere...
Is it possible? I tried escaping at various points but I'm not sure about the escaping rules when quotes are involved...
Edit: I think this link might be the issue (ie: it's a bug): Pipe in for loop breaks double quoted variables
#echo off
setlocal enableextensions disabledelayedexpansion
set "wmicpath=%windir%\System32\wbem\wmic.exe"
for /f "usebackq delims=" %%a in (`
^""%wmicpath%" COMPUTERSYSTEM GET SystemType ^| findstr /I "x64"^"
`) do (
echo %%a
)
If you look at the start and end of the inner command, you will see two additional ^" (a escaped double quote). Your problem is that the for command is spawning a separate instance of cmd to handle the inner command, and this separate instance is removing the initial and final double quotes.
Why escaped quotes? To avoid this additional quotes being paired with the double quotes in the command that could lead to some other parsing problems.
You can run cmd /? to obtain the help page (sorry, i have a spanish locale so i will not include the output here). You will see a section about the /C and /K usage explaining quote removal behaviour.
First of all I would change the command, WMIC allows you to use a query language LIKE operator which would in this case remove the need to pipe anything.
#Echo Off
Set "WMIC=%SystemRoot%\System32\Wbem\wmic.exe"
For /F "UseBackQ Skip=1" %%a In (
`""%WMIC%" ComputerSystem Where "SystemType Like 'x64%%'" Get SystemType"`
) Do For %%b In (%%a) Do Echo=%%b
Timeout -1
Then I may even change the format of the command such that I don't use back quotes.
#Echo Off
Set "WMIC=%SystemRoot%\System32\Wbem\wmic.exe"
For /F "Skip=1" %%a In (
'""%WMIC%" ComputerSystem Where (SystemType Like "x64%%") Get SystemType"'
) Do For %%b In (%%a) Do Echo=%%b
Timeout -1
Whilst this doesn't directly answer the question in the subject title, it does allow for your particular command to work correctly.
However neither are necessary to your particular command example, because you do not need the for loop to echo that output:
#Echo Off
Set "WMIC=%SystemRoot%\System32\Wbem\wmic.exe"
"%WMIC%" ComputerSystem Get SystemType|Find /I "x64"
Timeout -1
Change Find to FindStr if you feel the need.
>x64.txt ECHO x64
for /f "usebackq" %%a in (`"%wmicpath%" COMPUTERSYSTEM GET SystemType ^| findstr /I /g:x64.txt`) do (
might be a work-around, depending on your actual application and preferences.

windows 7 not generating txt report

I want to generate a txt file with my dns history. Although the batch script executes just fine on windows 8, when i run it on windows 7 it simply creates a blank txt file. Does anyone knows why this is happening?
Here's the batch script
#echo off
setlocal enableextensions
set "baseName=dnshistory"
set "count=0"
for /f "delims=%baseName%." %%a in (
'dir /b /o-d "%baseName%*.txt" 2^>nul'
) do ( set /a "count=%%a+1" & goto saveData )
:saveData
ipconfig /displaydns | find "Record Name" > "%baseName%%count%.txt"
Is you Windows 7 version in English too ?
Open a CMD windows and test just the command :
ipconfig /displaydns | find /i "Record Name"
and look if something is displayed.
If not, try just the command :
ipconfig /displaydns
and look the language used Then correct your code with the correct words.
IE in Portuguese it will be :
ipconfig /displaydns | find /i "Nome do Registro"
try this for a language independent solution:
:saveData
(for /f "tokens=2 delims=:" %%a in ('ipconfig /displaydns') do (
echo %%a| find "." |findstr /v /r "[0-9]$"
))>file.txt
(take every line, filter those, that have a . after a : (second token) and filter out all lines that end with a number)
EDIT another approach (because the above gives some unwanted lines):
find the first line after every ----------------- line:
#echo off
setlocal enabledelayedexpansion
ipconfig /displaydns |findstr /n "^" >a.txt
for /f "tokens=1 delims=:" %%a in ('findstr /c:" --------------" a.txt') do (
set /a line=%%a+1
for /f "tokens=1,2,* delims=:" %%i in ('findstr /B "!line!:" a.txt') do echo(%%k
)

Batch Scripting - Finding OS Version information - Variable Output

I have a script that works perfectly.
if not exist %SystemRoot%\system32\systeminfo.exe goto warnthenexit
systeminfo | find "OS Name" > osname.txt
FOR /F "usebackq delims=: tokens=2" %%i IN (osname.txt) DO set vers=%%i
echo %vers% | find "Windows 7" > nul
if %ERRORLEVEL% == 0 goto VERSION_7
However, when I try to print the results like so:
Echo Current OS:%vers% - 64 Bit
It prints the results with a really! long gap. Like so:
Current OS: Microsoft Windows 7 Enterprise - 64 Bit
Does anyone know why? or how I can remove the large gap?
Thanks a million!
I know your script "works perfectly", but is not much efficient.
SYSTEMINFO takes a lot of time and osname.txt may be avoided.
Check:
FOR /F "TOKENS=1,* DELIMS==" %%u IN ('WMIC OS GET CAPTION /VALUE') DO IF /I "%%u"=="Caption" SET vers=%%v
Changed
FOR /F "usebackq delims=: tokens=2" %%i IN (osname.txt) DO set vers=%%i
To
FOR /F "usebackq delims= tokens=2" %%i IN (osname.txt) DO set vers=%%i
*Changed the : to a %space% after delims...

Resources