Having trouble storing output of "wmic csproduct get vendor /format:list | findstr/c=" as a variable [duplicate] - batch-file

This question already has answers here:
Batch WMIC redirecting output and wrapping into variable
(5 answers)
Closed 2 years ago.
Thank you for checking out my question.
I am trying to:
get the output of a wmic query into a variable
Here is some background information for why I need to get this accomplished.
The policy at my job requires that laptops and tablets equipped with webcams have them disabled in the BIOS.
Now that we are teleworking we have a need to enable the webcams in the BIOS.
We have tools that can be used to enable BIOS features while the system is running.
I want to write a script that will psexec into a machine, fetch the vendor information and store it in a variable that can be accessed later in the script once psexec exits.
I can write the rest of my script without issue I think, however I'm having trouble figuring out how to store the results of the following command in a variable:
wmic csproduct get vendor /format:list | findstr/c=
For example, the output of that command on my machine is:
Vendor=Dell Inc.
I want to capture the output and store it in a variable for later use in the script I'll be writing so that I can process vendor specific BIOS manipulation.
I have tried
set sysvend=wmic csproduct get vendor /format:list | findstr/c=
But when I echo %sysvend% to see if it worked I get the following instead of what I wanted:
wmic csproduct get vendor /format:list | findstr/c=
If anyone knows how to do this I would greatly appreciate the help. I am open to other alternatives for determining the vendor.

Even easier than using find or findstr and without the problematic 0x0D0D0A line endings:
#Echo Off & SetLocal EnableExtensions
For /F Tokens^=6Delims^=^" %%G In (
'%__APPDIR__%wbem\WMIC.exe CSProduct Get Vendor /Format:MOF 2^>NUL'
) Do Set "vendor=%%G"
This solution also prevents unwanted trailing characters with the vendor name string, which can be a common occurrence.

There is a known wmic bug, so you need to parse wmic output using two nested loops, e.g. as follows:
FOR /F "tokens=1* delims==" %%s IN ('
wmic csproduct get vendor /value ^| find "="
') DO for /F "tokens=*" %%i in ("%%t") do SET "vendor=%%i"
Here the for loops are
%%s to retrieve the vendor value;
%%i to remove the ending carriage return in the value returned (wmic behaviour): each output line ends with 0x0D0D0A (CR+CR+LF) instead of common 0x0D0A (CR+LF).
See Dave Benham's WMIC and FOR /F: A fix for the trailing <CR> problem

Answer posted to demonstrate the command can be assigned and executed as a variable, Contrary to Neko's answer, as per the OP's question.
#Echo Off
Set Get.Vendor=^>"%TEMP%\Vendor.log" (wmic csproduct get vendor /value ^|
findstr /c:=) ^&^& (For /F "UsebackQ Tokens=2* Delims==^EOL" %%A In ("%TEMP%\Vendor.log") Do For /F "Delims=" %%T In ("%%A") Do Set "Vendor=%%~T") ^&^& Echo.!Vendor!
Setlocal EnableDelayedExpansion
%Get.Vendor%
pause

Use for %%i in (wmic csproduct get vendor /format:list ^| findstr/c=) do (set var=%%~I)
What this does is that the for loop variable %%i becomes the output of the command in the for loop which allows you to set another variable the for loop variable. You need the caret (^) before the | in the for loop since if you didn't, the command would pipe out of the for loop and not execute in the for loop. You could also just surround the command with double quotes (") and you wouldn't need to escape the pipe. As a result of the command, %var% would become equal to the output of your wmic command.
The final command will be:
#echo off
for /f "tokens=* delims==" %%i in (' wmic csproduct get vendor /format:list ^| findstr /c:"=" ') do (set var=%%~i)
echo %var%
rem echoing var to make sure the variable is what you wanted
Output for me:
Vendor=Microsoft Corporation
If you want the output to be Microsoft Corporation specifically, you can add:
set var=%var:~7%
to remove the first 7 characters. You can also change tokens to 2* instead of *. :
for /f "tokens=2* delims==" %%j in (' wmic csproduct get vendor /format:list ^| findstr /c:"=" ') do (set var=%%~j)
Outputs:
Microsoft Corporation
Notes:
In batch-files, unlike powershell, you cannot set a variable as a command and have it become the output which is why the conventional way to set output of a command to a variable is using the for loop. Also, just preference, I would suggest using the /value switch rather than /format:list.
Tested and works for me

Related

Batch File: Setting Variable from second output line error with space on output "Was Unexpected at this time"

I have been fighting with this for 2 hours now. I need to set a variable from a second line output of a command. I found this code here at stackoverfglow:
for /f "skip=1delims=" %%a in (
'%SystemRoot%\System32\wbem\wmic.exe CSPRODUCT GET NAME'
) do set sid=%%a&goto next
The output for wmic.exe CSPRODUCT GET NAME is:
Name
PowerEdge T610
but when I run the batch file I get:
>set sid=PowerEdge T610
T610 was unexpected at this time.
I tried putting quotes everywhere.
I'm doing this script to check if the computer is a VirtualBox o VMware machine, the idea is to set a variable with the output of that command then compare it to "VirtualBox". But physical computers have product name with spaces.
THANKS!
I would offer the following method, as it will capture the full string without any potentially unwanted trailing space characters:
#For /F Tokens^=6Delims^=^" %%G In ('""%__AppDir__%wbem\WMIC.exe" CSProduct Get Name /Format:"MOF" 2>Nul"')Do #Set "SID=%%G"
Note: If you are using Windows 7, the use of some output formats may be broken, as the relevant .xsl stylesheets are located inside a language specific subdirectory which is not read by default. This issue can be worked around, by copying/moving or creating links to, all of the .xsl files one level higher, i.e. inside the wbem directory. (see potential alternative fix at the foot of this answer)
Alternatively, you could omit the for-loop completely, and instead of defining a variable, just use conditional statements:
#("%__AppDir__%wbem\WMIC.exe" CSProduct Where "Name Like '%%VirtualBox%%' Or Name Like '%%VMWare%%'" List Instance /Format:"List" 2>NUL|"%__AppDir__%find.exe" "__">NUL&&(Echo Virtual)||Echo Physical)&Pause
Note: In this example please ensure that you replace VirtualBox and/or VMWare as/if necessary. You can obviously replace the respective Echo commands with your chosen commands after testing.
Alternatively, for the actual process you need it for, based upon your comments, the following should also suffice:
#("%__AppDir__%wbem\WMIC.exe" ComputerSystem Where "Model Like '%%Virtual%%'" Get /Value 2>NUL|"%__AppDir__%find.exe" "=">NUL&&(Echo Virtual)||Echo Physical)&Pause
This should pick up a Hyper-V machine, (Model:Virtual Machine), a VMware machine, (Model:VMware Virtual Platform), and an Oracle VM, (Model:VirtualBox).
Here is a modified batch-file, which is intended to fix the potential Format issue in windows-7, as mentioned in my first example above:
#Echo Off
Set "XSL=MOF"
For /F "Delims==" %%G In ('"Set SID 2>NUL"')Do Set "%%G="
For /F "EOL=MDelims=" %%G In (
'""%__AppDir__%wbem\WMIC.exe" OS Get MUILanguages,Version 2>NUL"'
)Do For /F Tokens^=2^,4-5Delims^=.^"^ %%H In ("%%G"
)Do If %%I Equ 6 If %%J Equ 1 (Call :Target "%__APPDIR__%wbem\%%H\%XSL%"
)Else Call :Target "%XSL%"
Set SID 2>NUL&&Pause
GoTo :EOF
:Target
For /F Tokens^=6Delims^=^" %%G In (
'""%__AppDir__%wbem\WMIC.exe" CSProduct Get Name /Format:"%~1" 2>Nul"'
)Do Set "SID=%%G"
Line 9 is where you'd place your code, replacing mine which was added just for demonstration purposes.

Batch - Check Dell bios version and update script

I'm creating a script to automatic update BIOS firmware for our Dell PC. We have multiple model here, so I need to check the model
C:\Users\me>wmic csproduct get name
Name
OptiPlex 3020
And also bios version
C:\Users\me>wmic bios get smbiosbiosversion
SMBIOSBIOSVersion
A09
Now I will put the bios updater somewhere on our network with filename format model_version.exe.
How should I do to get the model and version in to 2 variables and in the end I just run
//path/to/the/updater/"%model%_%version%.exe" /s /r
to update the bios automatically, if the PC already on the latest bios version, just skip the script?
Thank a lot for your help.
I recently had this same issue, needing to update a bunch of Acer laptops BIOS to fix the trackpads. Here is the solution I came up with, using the linked Batch file set wmi output as a variable from JosefZ's comment on your question.
By using /value switch of wmic we can get the wmic output on one line and then use 'for' with delims to tokenize it (split into two variables) and store the 2nd token as our desired variable.
Check if the file exists, then pass through to the "start" command so the bat file won't exit until after it has run the updater. (This is useful if combining with pushd to access a network path so the drive letter doesn't drop out)
for /f "tokens=2 delims==" %%f in ('wmic csproduct get name /value ^| find "="') do set "model=%%f"
for /f "tokens=2 delims==" %%f in ('wmic bios get smbiosbiosversion /value ^| find "="') do set "version=%%f"
IF EXIST "\\path\to\the\updater\%model%_%version%.exe" start "" /WAIT "\\path\to\the\updater\%model%_%version%.exe" /s /r

WMIC commands to change computer name to BIOS serial number

I'm new with batch file and wmic and after researching StackOverflow I've found few answers which overlap but not producing expected output when put together.
Problem:
Create a batch file to change computer name (not on domain):
use wmic bios get serialnumber and assign the value to the variable comp_name, then display the value of this variable;
change computer name to the value of the variable comp_name;
So for 1.:
FOR /F %%F IN ('wmic bios get serialnumber') DO (
SET comp_name=%%F
)
ECHO %comp_name%
Followed by 2.:
WMIC computersystem where name="%computername%" rename name=%%comp_name%%
edit: got a 1. part correct - works as expected - fetching serial number and displays the variable's value. However part 2. still throwing errors:
O:\>wmic computersystem where name="TOM-PC" rename NAME=
Invalid named parameter list.
Hint: <named param list> ::= <named param> | <named param> <named param list> where <named param> ::= <param name>=<param value>
If I understand correctly - the NAME=... part of the last command don't recognise variable initialised above. So how to use a comp_name as a parameter for wmic command?
edit .2
"Why are you using doubled % signs in name=%%comp_name%%?" by aschipfl - I reverted to my original question - used double % and now getting different error - 87 which tells me more about the problem. using singles % produce the error listed above. I'm not sure if the problems lies in single or doubles% or somewhere else.
edit .3
Further research shows that wmic bios get serialnumber returns in fact three values each in new line
C:\Windows\system32>wmic bios get serialnumber
SerialNumber
BY3VF02
that is - SerialNumber string followed by actual serial number in new line and last one with just empty line. So (I hope) the final questions - how to assign only the second value to my variable please?
Give a try for this batch code :
#Echo Off
For /F "tokens=2 Delims==" %%A In ('WMIC Bios Get SerialNumber /Value') Do (
For /F "Delims=" %%B In ("%%A") Do (
Call :RenamePC "%%B"
Call :Ask4Reboot
)
)
pause & Exit /B
::**********************************************************************
:RenamePC
WMIC ComputerSystem where Name="%ComputerName%" call Rename Name="%~1"
Exit /B
::***********************************************************************
:Ask4Reboot
(
echo Set Ws = CreateObject("wscript.shell"^)
echo Answ = MsgBox("Did you want to reboot your computer ?"_
echo ,VbYesNo+VbQuestion,"Did you want to reboot your computer ?"^)
echo If Answ = VbYes then
echo Return = Ws.Run("cmd /c shutdown -r -t 60 -c ""You need to reboot in 1 minute."" -f",0,True^)
echo Else
echo wscript.Quit(1^)
echo End If
)>"%tmp%\%~n0.vbs"
Start "" "%tmp%\%~n0.vbs"
Found this batch here:
https://community.spiceworks.com/topic/1912255-batch-file-to-use-wmic-commands-to-change-computer-name
Worked for Win 10 Ent v1803.
If you need prefix etc, simply add to name before / after variable.
setlocal
wmic bios get serialnumber | find /I /V "SerialNumber" > "%temp%\sn.txt"
set /p comp_name=<"%temp%\sn.txt"
wmic computersystem where name="%computername%" rename name=%comp_name%
del "%temp%\sn.txt"
endlocal
The following, as long as your bios serials are valid computer names, should do it:
#Echo Off
For /F "Skip=1 Delims=" %%A In ('WMIC Bios Get SerialNumber'
) Do For /F "Delims=" %%B In ("%%A") Do Call :RenPC %%B
Exit/B
:RenPC
WMIC ComputerSystem Where Name!="%~1" Call Rename Name="%~1"
The PC will have to be rebooted before the new name will take effect.

Batch WMIC redirecting output and wrapping into variable

I'm trying to use WMIC to remove some old printers on our older print servers
if I use the below syntax from the command line it works
WMIC PRINTER WHERE "SERVERNAME LIKE '%%OLDSERVERNAME%%'" DELETE
I was asked to see if I could make it replace the printers or update them to spare the helpdesk from getting "how do I add my printer" calls
I tried some variation with SET to set the properties for SERVERNAME, it appear to process, but nothing changes and doing a GET shows the old value still.
so I figured I could do a FOR /F loop, wrap the name of the printer (sharename) in a variable and then use another command to recreate the printers, after the offending printers have been deleted.
here's my script
#ECHO
ECHO Gathering Installed Printer Information...
FOR /F "tokens=1 skip=1" %%A IN ('WMIC PRINTER WHERE "Servername like "%%printaz1%%"" get sharename') DO SET PRINTERNAME=%%A
ECHO %PRINTERNAME%
so you would think you'd get the value all wrapped up in a nice variable to do with as you wish but no, I turned echo on and it appears that the variable gets set back to null as soon as it's captured
my output looks like this...
FOR /F "tokens=1 skip=1" %%A IN ('WMIC PRINTER WHERE "Servername like "%%printaz1%%"" get sharename') DO SET PRINTERNAME=%%A
SET PRINTERNAME=nameofprinter
SET PRINTERNAME=
ECHO
ECHO is on.
would love some thoughts on why it seems to be dumping the string.
Powershell and VBScript aren't out of the option either, I'm familar with both, just this seemed possible, and I really don't want to start over.
WMIC is returning two lines, one with the printername, and one empty.
The solution to this is to test for empty lines.
ECHO Gathering Installed Printer Information...
FOR /F "tokens=1 skip=1" %%A IN ('WMIC PRINTER WHERE "Servername like "%%printaz1%%"" get sharename') DO if not "%%A"=="" SET PRINTERNAME=%%A
ECHO %PRINTERNAME%
what you are looking for is this:
for /f "skip=2 tokens=2 delims=," %%A in ('WMIC PRINTER WHERE "Servername like "%%printaz1%%"" get sharename /format:csv') DO SET PRINTERNAME=%%A
ECHO %PRINTERNAME%
Explanation:
The unicode output of wmic includes a carriage return which is captured by the FOR /F which is what you do not want, as it means the 'enter' becomes part of your variable (%%A) and it also contains an empty line, which again will be outputted to %%A.
My example does the following:
/format:cvs -- will output a comma seperated output so we can capture using the delimiter ,
skip=2 -- will skip the empty line at the beginning and skip the header row of the csv.
tokens=2 -- the csv output contains the name,value as output, but you only want value, which is the second token.
by the way, because we no longer include space as a seperate it should even work with spaces in the value. give it a try.
I got around the UNICODE carriage return (which is really the problem here) like this:
#echo off
FOR /F "usebackq tokens=1,2 delims==" %%A IN (`wmic %* /VALUE ^| findstr "="`) DO (call :OUTPUT %%A "%%B")
exit /b
:OUTPUT
echo %1=%2
Save that as "wmi.bat"
and execute your query like this:
wmi.bat printer where 'name like "HP%"' get name
My output looks like this:
Name="HP1C0BCA (HP Officejet Pro 276dw MFP)"
Name="HP Officejet Pro L7500 Series"
Name="HP Officejet Pro 276dw MFP PCL 6"
You can imagine how you can play with this.
the "%%B" portion puts all of the output of /VALUE (including spaces) into the %2
%%A captures the object id, which becomes %1 which is handy if you use this to log all sorts of information from WMI. You don't have to worry about the Unicode carriage return anymore.
The big advantage of this approach is that you have a clever batch file which overcomes the limitations that wmic gives you when using it inside a script, and you can use it for anything.
you can use the STDOUT of the batch file as the parameter for anything else, even as input to wmic!
The most secure and general variant is to nest another for /F loop, like this:
for /F "skip=1 usebackq delims=" %%A in (`
wmic Printer where 'Servername like "%%printaz1%%"' get ShareName
`) do for /F "delims=" %%B in ("%%A") do set "PRINTERNAME=%%A"
The problem is the Unicode output of the wmic command and the poor conversion to ANSI text by for /F, which leaves some orphaned carriage-return characters, which in turn lets appear some additional lines as non-empty. The second for /F loop gets rid of these conversion artefacts.
I also replaced the tokens=1 option by delims= in order not to truncate the returned item at the first white-space.
Take also a look at the following related answers by user dbenham:
Why is the FOR /f loop in this batch script evaluating a blank line?
For /F with wmic unwanted output
#ECHO
ECHO Gathering Installed Printer Information...
FOR /F "tokens=1 skip=1" %%A IN ('WMIC PRINTER WHERE "Servername like "%%printaz1%%"" get sharename') DO (
SET PRINTERNAME=%%A
goto end
)
:end
ECHO %PRINTERNAME%

batch that return drive letter of USB with specific volume name

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.
)
)

Resources