For loop not working properly in batch file - for-loop

I am trying to get the current operating system using this batch file. It is:
#echo off
for /f "skip=1 tokens=1* delims= " %%a in ('wmic path win32_operatingsystem get caption') do set _os=%%a %%b %%c %%d
echo You are running %_os%.
goto :eof
My operating system is windows 7 so I expected it will return:
You are running Microsoft Windows 7 Ultimate.
But it returns you are running %c %d.
Why I am getting this result?

There are a few ways, one already posted by Mofi in the above comment which already demonstrates the main change using /value. You can also use the caption itself as variable name with its value:
#echo off
for /f "delims=" %%a in ('wmic path win32_operatingsystem get caption /value') do set %%a>nul 2>&1
echo %caption%

Related

Having trouble with a script to find the date and time in a batch file

So, I have a script to log the date and time in a text file:
for /f "tokens=2 delims==" %%G in ('wmic os get localdatetime /value') do set datetime=%%G
set year=%datetime:~0,4%
rem pause
set month=%datetime:~4,2%
set day=%datetime:~6,2%
set /a day2=day+5
echo %year%/%month%/%day2%> C:\WLT\Init\lastoptim.txt
And a similar one in a script that runs on startup:
for /f "tokens=2 delims==" %%G in ('type C:\WLT\Init\lastoptim.txt') do set datetime2=%%G
set year=2%datetime2:~0,4%
rem pause
set month2=%datetime2:~4,2%
set day2=%datetime2:~6,2%
set /a day3=day2+1
echo %year2%/%month2%/%day3%> lastoptim2.txt
echo %year2%/%month2%/%day3%
But it doesn’t work. What I need is a script to extract a date from %date% into a text file, and then another one to take that date, see if the current date is X number of days later, and if it is, then run a command.
Would like this script to be entirely dependent on cmd, because this is going to be used on systems as far back as XP. Using an external app (e.g. an exe that prints out the date in a specific format) would be fine.
Your question still not clear for me, but if you want to add one day or one month for your dates, here is an example :
#echo off
Title Manipulate DATES WITH BATCH
#for /f "tokens=* delims=" %%a in ('wmic os get LocalDateTime /value') do for /f "tokens=* delims=" %%# in ("%%a") do set "%%#"
:: Store the local date inside a variable
set "CurrentDateTime=%LocalDateTime%"
set "CurrentDate=%CurrentDateTime:~0,4%/%CurrentDateTime:~4,2%/%CurrentDateTime:~6,2%"
:: Here Adding One day
#for /f %%a in ('Powershell -C "(Get-Date).AddDays(1).ToString('yyyy/MM/dd')"') do set "NextDay=%%a"
:: Here adding 1 month
#for /f %%a in ('Powershell -C "(Get-Date).AddMonths(1).ToString('yyyy/MM/dd')"') do set "NextMonth=%%a"
echo( CurrentDate : %CurrentDate%
echo( NextDay : %NextDay%
echo( NextMonth : %NextMonth%
pause

BATCH: Variable set by for loop ends up being blank

I am trying to run the following script
#ECHO OFF
FOR /F "Skip=1 Tokens=*" %%G IN ('WMIC COMPUTERSYSTEM GET Manufacturer') DO (SET "DeviceOEM=%%G")
ECHO OEM: %DeviceOEM%
PAUSE
However all I get is "ECHO OEM:", which indicates that %DeviceOEM% is blank.
Now if I run
FOR /F "Skip=1 Tokens=*" %%G IN ('WMIC COMPUTERSYSTEM GET Manufacturer') DO (ECHO %%G)
PAUSE
Then I get a real answer of my OEM.
I don't understand where this SET command is failing.
When delim is issued on = it will only assign the value after the = to the value. We therefore change the wmic command to issue the result with /value which will return Manufacturer=<name of OEM> where we only use everything post =
#echo off
For /F "tokens=2*delims==" %%G in ('WMIC COMPUTERSYSTEM GET Manufacturer /value') do SET "DeviceOEM=%%G"
echo OEM: %DeviceOEM%

cmd taskkill work with hardcoded PID value but not with same value as variable

I am facing a strange situation inside a Windows batch script that I currently work on.
In this section I extract the PID of a parent process, using its child's name (%PROCESS_NAME%). It work well and I can echo PARENT_PID without problems :
for /f "usebackq tokens=2 delims==" %%a in (`wmic process where ^(name^='%PROCESS_NAME%'^) get parentprocessid /value`) do (
set PARENT_PID=%%a
)
echo !PARENT_PID!
Result show the expected value :
16392
The problem is in next line :
taskkill /f /t /pid !PARENT_PID!
The process doesn't get killed and the script showing a strange text (I am working in a french environment) :
" est introuvable.sus "16392
If I replace !PARENT_PID! with the hardcoded PID value like this :
taskkill /f /t /pid 16392
Everything works fine and the parent process and its child are killed.
I tried many thing but cannot figure out what is wrong.
If anyone has an idea, I'm interested to kow, thanks !
Try like this and you'll see the problem:
#echo off
setlocal enableDelayedExpansion
for /f "usebackq tokens=2 delims==" %%a in (`wmic process where "name='explorer.exe'" get parentprocessid /value`) do (
set PARENT_PID=%%a
)
echo -!PARENT_PID!-
WMIC output sets one additional carriage return at the end. Here you can find a workaround (with an additional for loop):
#echo off
setlocal enableDelayedExpansion
for /f "usebackq tokens=2 delims==" %%a in (`wmic process where "name='explorer.exe'" get parentprocessid /value`) do (
for /f "tokens=* delims=" %%# in ("%%~a") do set "PARENT_PID=%%#"
)
echo -!PARENT_PID!-
I've always opted to try to prevent an issue from happening, rather than fix it later. For that reason, here are some alternative suggestions for trying to overcome the unwelcome line feed issue.
If you can include a property before and after the target property, (in this case ParentProcessID), and be sure that those 'pre' and 'post' properties will not be NULL, you can retrieve your value without the problematic carriage return.
Example:
#Set "PPID="
#For /F "EOL=H Tokens=2" %%A In ('""%__AppDir__%wbem\WMIC.exe" Process Where Name="%PROCESS_NAME%" Get Handle,ParentProcessID,SessionID 2>NUL"')Do #Set "PPID=%%A"
#Set PPID 2>NUL
#Pause
Alternatively, you could use wmic's /Format option.
Example:
#Set "PPID="
#For /F "Skip=1 Tokens=2 Delims=," %%A In ('""%__AppDir__%wbem\WMIC.exe" Process Where Name="%PROCESS_NAME%" Get ParentProcessID /Format:CSV 2>NUL"') Do #Set "PPID=%%A"
#Set PPID 2>NUL
#Pause
Note: There's an issue that I'm aware of in windows-7, whereby the location of required .xsl files is not correct. One fix is to move those files into the correct directory, \Windows\System32\wbem. Alternatively find its location and specify it directly within the value. On the systems I've used, I found csv.xsl in \Windows\System32\wbem\en-US, so you could use, (adjusting as necessary):
#Set "PPID="
#For /F "Skip=1 Tokens=2 Delims=," %%A In ('""%__AppDir__%wbem\WMIC.exe" Process Where Name="%PROCESS_NAME%" Get ParentProcessID /Format:"%__AppDir__%wbem\en-US\csv.xsl" 2>NUL"') Do #Set "PPID=%%A"
#Set PPID 2>NUL
#Pause

How can I use batch to determine what version of windows a computer is runing?

While scripting it is necessary to determine what version of Windows a computer is running. The only issue is that Windows-10 and Server-2016 have the same version number.
This is the code currently. In this state, Windows10 and Server2016 are identified with the same number wmic os get outputs 10.0.18329 (which doesn't work).
for /f "tokens=4-5 delims=. " %%i in ('ver') do set Operating=%%i.%%j
if "%Operating%" == "6.3" set Operating=Windows81
if "%Operating%" == "6.2" set Operating=Windows8
if "%Operating%" == "10.0" set Operating=Windows10
if "%Operating%" == "10.0" set Operating=Server2016
echo Is %Operating% your operating system?
What I would like to do is parsewmic os get name to get the OS name. This is showing some challenges because the output is multiple lines and there is an arbitrary number of characters before and after the OS name ('Windows 10').
This is the output of wmic os get name on windows 10 pro:
Name
Microsoft Windows 10 Pro|C:\WINDOWS|\Device\Harddisk1\Partition3
This is the output of wmic os get name on Server 2016:
Name
Microsoft Windows Server 2016 Standard|C:\Windows|\Device\Harddisk0\Partition2
I know you've already chosen a solution, but if this is related to the last question you asked, now deleted, where you're only trying to determine between Windows 8, Windows 8.1, Windows 10 and Windows Server 2016 then I would have suggested something along these lines:
#Echo Off
Set "_S="
For /F "EOL=P Tokens=*" %%A In ('"WMIC OS Get ProductType,Version 2>Nul"'
) Do For /F "Tokens=1-3 Delims=. " %%B In ("%%A") Do Set /A _S=%%B,_V=%%C%%D
If Not Defined _S Exit /B
If %_V% Lss 62 Exit /B
If %_S% Equ 1 (If %_V% Equ 62 Set "_S=Windows8"
If %_V% Equ 63 Set "_S=Windows81"
If %_V% Equ 100 Set "_S=Windows10"
) Else If %_V% Equ 100 (Set "_S=Server2016") Else Exit /B
Set _S
Pause
Exit /B
[Edit /]
…and for a generic method, you may find this useful, especially the use of the Caption property, (which I'd suggest is much better than using the Name property, splitting it at the first pipe character, running it through another For loop then removing one or more trailing space characters).:
#For /F Tokens^=6Delims^=^" %%A In ('WMIC OS Get Caption/Format:MOF')Do Set "_S=%%A"
To test it just add a second line:
#Set _S&Pause
Note: This method may have issues on some earlier operating systems due to a bug preventing them finding the location of the .xsl file. There are workarounds for this, either copy the .xsl files from your 'language' directory up a level, or provide the full path to the .xsl file, e.g. /Format:"%__AppDir__%wbem\en-US\MOF.xsl".
How about just straight forward...
#echo off
for /f "skip=1 delims=|" %%i in ('wmic os get name') do echo %%i & exit /b
This is simple:
#echo off
for /F "skip=1 tokens=2-4 delims=| " %%A IN ('wmic os get name') do (
set "os=%%A %%B %%C"
)
echo You are using %os%.
Another possible solution to include all versions of Windows:
#echo off
for /F "skip=1 delims=|" %%A IN ('wmic os get name') do (
for /F "delims=" %%B IN ("%%A") do (
set "os=%%B"
)
)
echo You are using %os:Microsoft =%.
pause
exit /b
Which will extract OS, substracting Microsoft<space> at the end in both cases.
In the second case, two loops are used, since wmic has unusual line endings (<CR><CR><LF>).
You can use the ver command, here is an example:
#echo off
for /f "useback delimes=;" %%a in (`ver`) do set ver=%%a
echo The computer version your running is %ver%
Use the variable %ver% as the version you are running, I use it to echo the version but you can do anything with it

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