So I'm making an installer which installs in a specific file that would be located in one of multiple drives, and the file could be in any drive (C:\, E:\, D:\, etc.). So for example: I want to install ZK47 in E:\KNX\44C, but I want the system to automatically find the file KNX without going to E:\ and without user input.
look in all harddisks (Mediatype=12) if the folder exists:
for /f "tokens=2 delims==:" %%i in ('wmic logicaldisk where mediatype^=12 get caption /value') do if exist %%i:\KNX\44C echo found on drive: %%i:
for /f %%i in ('command') do ... is a common way to process the output of a command.
wmic logicaldisk get caption lists all existing drive letters.
where mediatype=12 tells it to list only harddisks (inside the for construct you have to escape the = with a caret ^).
/value defines the output format.
"normally" you would use "tokens=2 delims==" to get the string after = (C:). By using : as additional delimiter I avoid dealing with the ugly line endings of wmic.
Related
Stack community good day! Thank you in advance for your time
I would like to create a bat file in order to autocreate an iso file from the DVD drive. So the logic will be:
Find which is the CD/DVD drive (from many drives)
And use that result as a variable (of the drive: for example F:) which will be executed in the following command:
cdbxpcmd.exe --burn-data -folder:F:\ -iso:C:\donalds.iso -format:iso
So in the previous command, the F:\ will be the variable, lets say %input%:\ which the program cdbxpcmd will use in order to create an iso from that drive.
I have found the following script that finds the drive letter,
from here: https://itectec.com/superuser/windows-how-to-detect-dvd-drive-letter-via-batch-file-in-ms-windows-7/
#echo off
setlocal
for /f "skip=1 tokens=1,2" %%i in ('wmic logicaldisk get caption^, drivetype') do (
if [%%j]==[5] echo %%i
)
endlocal
Do you believe that we could combine them? And how? Any suggestions?
You could use cdbxpcmd.exe itself to locate your drive:
Two line batch-file example:
#Set "CDBXP=C:\Program Files\CDBurnerXP\cdbxpcmd.exe"
#For /F "Tokens=2 Delims=()" %%G In ('^""%CDBXP%" --list-drives^"') Do #"%CDBXP%" --burn-data -folder:%%G -iso:"C:\donalds.iso" -format:iso
Just change the location where you have your cdbxpcmd.exe command line utility between the = and the closing " on line 1.
Alternatively, you could still use WMI, but personally, I would not use Win32_LogicalDisk, I would instead use Win32_CDROMDrive, which could verify both that a CDROM disk is loaded, and that it contains readable data.
Single line batch-file example:
#For /F Tokens^=6^ Delims^=^" %%G In ('%SystemRoot%\System32\wbem\WMIC.exe Path Win32_CDROMDrive Where "MediaLoaded='True' And DriveIntegrity='True'" Get Drive /Format:MOF 2^>NUL') Do #"C:\Program Files\CDBurnerXP\cdbxpcmd.exe" --burn-data -folder:%%G\ -iso:"C:\donalds.iso" -format:iso
Just change the location where you have your cdbxpcmd.exe command line utility, remembering to leave the doublequotes in place for best practice.
I need to realize the following algorithm in a Windows 10 batch file.
Loop through a directory and search for files.
For each file found, get its manufacturer's name.
If the manufacturer's name is for example "Microsoft", delete the file.
I've already made some tries with a FOR loop and the WMIC DATAFILE without any success; I just can't get the manufacturer's name into a variable for comparison.
I use the following code to loop through all the files (and directories):
pushd C:\<path>\Temp
for /f "tokens=*" %%F in ('dir /a /b') do (<something_with_%%F>)
popd
Then, I use the following code to get a file's manufacturer name:
wmic datafile where name="C:\\<path>\\Temp\\<file_name>.<ext>" get manufacturer
This preceding code will output (if used with the "echo" command) the following (if the target file belongs to Microsoft):
Manufacturer
Microsoft
Now, the problems begin when I try to use those two pieces of code together to realize the algorithm (pseudo-code) described above. Unless there's another way to do this?
There is no need to piece those two codes together, there is functionality buit in to the WMIC command.
For Example:
For /F "Skip=1 Delims=" %%A In ('
"WMIC DataFile Where (Drive='C:' And Path='\\<path>\\Temp\\' And Not Manufacturer Is Null) Get FileName, Manufacturer, Version"
') Do For /F "Delims=" %%B In ("%%A") Do Echo(%%B
You will obviously need to replace \\<path>\\Temp\\ with your true path, (must begin and end with \\).
You could even target only exe files by adding And Extension='exe' to your Where block.
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
So, I've been working on a batch file to collect specific system information, I've run into a road block with opening an INI file that's on the network installation. So obtaining the path is:
for /f "tokens=2*" %%a in ('REG Query "HKCU\SOFTWARE\Zephyr Associates, Inc." /v StyleDir 2^>nul') do set "StyleDir=%%~b"
for /f "tokens=2*" %%a in ('REG Query "HKLM\SOFTWARE\Zephyr Associates, Inc." /v StyleDir 2^>nul') do set "StyleDir=%%~b"
for /f "tokens=2*" %%a in ('REG Query "HKLM\SOFTWARE\Wow6432Node\Zephyr Associates, Inc." /v StyleDir 2^>nul') do set "StyleDir=%%~b"
cd %StyleDir%
So in this scenario, let's say %StyleDir% is //Server/StyleDir/
Later on in the script we read the Style.ini file with the following:
for /f "tokens=2 delims==" %%a in ('findstr SQLiteHome style.ini') do set SQLiteHome=%%a
for /f "tokens=2 delims==" %%a in ('findstr Server style.ini') do set SQL=%%a
for /f "tokens=2 delims==" %%a in ('findstr DataHome style.ini') do set DataHome=%%a
At this point I get an error saying we're unable to read the Style.ini. Within the Style.ini I have the following:
[Default]
DataHome=C:\ProgramData\Zephyr\Data\
SQLiteHome=C:\ProgramData\Zephyr\Data\
[DataBaseList]
Tons of other lines I don't need to read Right now....
Later I populate a txt file that records the information. That script is as follows:
::Output
echo StyleDir: %StyleDir% >> SystemInformation.txt
echo SQLiteHome: %SQLiteHome% >> SystemInformation.txt
echo SQL Server: %SQL% >> SystemInformation.txt
echo DataHome: %DataHome% >> SystemInformation.txt
So is there a special way that I could get this info recorded from the INI file? I've had thoughts about temporarily mapping a network drive, but the problem with that is knowing what network drives are already mapped so that I don't break what's already there. I'm not even 100% sure that this has to do with the UNC path at all, I just know that when the INI is locally on C:\ that it can be read, but on the network it cannot. Any suggestions for what to try?
Another thing I've noticed is that I can open the Style.ini from a batch file just fine, regardless of the location. I just can't Read it for some reason.
You said:
I just know that when the INI is locally on C:\ that it can be read,
but on the network it cannot.
That's not true. You can read ini files with UNCs like this:
\\ServerName\directory\any.ini
The error may be somewhere else, such as unmatched quotes, authentication or missing file. Knowing what the exact error message you get would help debug the precise reason.
Expanded in response to complete error msg:
CMD does not support UNC paths
Implies removing this line
cd %StyleDir%
in your batch file as you cannot cd unless you map to a drive letter first. Consult map /help for details. Or you can avoid cd'ing to that folder by fixing the findstr command to use the UNC directly, such as:
findstr stringToSearch \\full\UNC\path\to\file.ini
Which option you choose will depend on what is being done to the found strings. You mention you are populating those strings, but not where. If populating to a file on the remote server, use the drive map option. If populating locally, then use the UNC option.
I figured it out, all you have to do is use
pushd \\server\dir
instead of
cd \\server\dir
when pointing to the path. Figures it would be something easy. I still get an error, but it'll proceed past it, which is fine by me :-)
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%