1

First post here, so apologies if I don't do this quite right.

I'm trying to output the OS version on a remote Windows PC, but I keep getting unwanted data. Executing this batch file:

@echo off
set /p hostname=PC hostname?
echo.
FOR /F "skip=1 tokens=*" %%A in ('wmic /node:%hostname% OS get caption') DO echo %%A
echo.
pause

Returns this result:

Microsoft Windows 7 Professional
Echo is off.

I was able to remove the Caption output using skip=1 but I don't understand where the echo command is coming from. Splitting out the commands didn't help, but turning echo on shows that, apparently, the looped wmic command is outputting echo after outputting the OS version, so, obviously, when echo is off, I get the final output: Echo is off. Can anyone help me understand why the echo output is happening?

Matt D
  • 13
  • 5
  • I can tell you why it's happening, but not how to stop it. The wmic output is three lines if you run it from a command prompt: `Caption`, `Microsoft Windows 7 Professional`, and a blank line. The blank line is causing %%A to be empty on the third call to `DO echo %%A`, which is resulting in just `echo` being executed, which causes the current state of ECHO to be output (*Echo is off*). – Ken White Jan 08 '16 at 19:58

4 Answers4

3

Magoo identified the source of the problem - the conversion of WMIC unicode output to ANSI is flawed in that each line ends with CRCRLF instead of the normal CRLF.

FOR /F breaks at (and strips) each LF, leaving CRCR. FOR /F strips the last character from each line if and only if it happens to be a CR, so that leaves one CR at the end of every line. FOR /F ignores empty lines, but CR is not an empty line, hence the unwanted Echo is off. output.

Magoo and Squashman have provided workable solutions to your problem, but they are not generic solutions that apply to all FOR /F - WMIC situations. A common issue arises when FOR /F output is stored in variables - the unwanted CR is often at the end of the value, which can cause problems later on.

We can use the known mechanics of FOR /F to strip the unwanted CR from every line by simply adding an extra FOR /F.

So the generic template that always works looks like

for delims^=^ eol^= %%. in ('wmic ....') do for /f "whatever options you need" %%A in ("%%.") do ...

or if you need to skip N lines, then

for skip^=N^ delims^=^ eol^= %%. in ('wmic ....') do for /f "whatever options you need" %%A in ("%%.") do ...

The arcane syntax in the first FOR /F sets both DELIMS and EOL to nothing. If you know that none of your output begins with ;, then you can simply use "delims=", or "skip=N delims=". This is the case in your situation.

So the solution becomes:

for /f "skip=1 delims=" %%. in ('wmic /node:%hostname% OS get caption') do for /f "delims=" %%A in ("%%.") do echo %%A
dbenham
  • 127,446
  • 28
  • 251
  • 390
  • How would you do this with the command `wmic datafile where name="C:\\file.exe" get Version` directly typed in the cmd? – Agostino Dec 09 '21 at 19:08
1

Pipe it to the find command.

@echo off
set /p hostname=PC hostname?
echo.
FOR /F "tokens=1,2 delims==" %%A in ('wmic /node:%hostname% OS get caption /value ^|find /I "caption"') DO echo %%B
echo.
pause
Squashman
  • 13,649
  • 5
  • 27
  • 36
  • sorry if my post was confusing. I only want the actual OS name. I have already filtered out the "caption" header, so I definitely don't want to find it. What I need is for the last iteration of the loop, which is a blank line, to go away. Ken White pointed out above, that is what's causing the unwanted `echo is off`. I need to get that part out. – Matt D Jan 08 '16 at 20:25
  • @MattD, I was originally testing the the `/value` and then took it out. The code is updated. Should work the way you want it now. – Squashman Jan 08 '16 at 21:12
1

I'd suggest

set "remotever="
FOR /F "skip=1 tokens=*" %%A in ('wmic /node:%hostname% OS get caption^|more') DO if not defined remotever set "remotever=%%A"
echo %remotever:~0,-1%

more is the classic batch method to conver wmic's unicode output to ANSI.

But there's a catch. Apart from Unicode, WMIC "ends" its lines with CRCRLF not CRLF and the penultimate CR is then included in the value assigned to the variable (hence echo the substring not including the last character - and you'll find some trailing spaces...).

(as a slightly easier demo, try echo q%%Aj in your original - you'll find the q is overwritten by the j)

Hence, to capture the first line out, set a variable to nothing, then in the for loop set it to the value you want to capture, but gate the set with if not defined.

Magoo
  • 77,302
  • 8
  • 62
  • 84
  • Putting WMIC in FOR /F converts the output to ANSI on its own - there is no need for MORE. The CR CR LF issue remains either way. – dbenham Jan 09 '16 at 14:39
  • As @dbenham mentions, there's no need for `more.com`. wmic.exe hard codes using a lossy OEM encoding for pipes and the console (not Unicode for the console nor even the current console codepage, which makes no sense), and UTF-16 Unicode for disk files. Since `for /f` decodes using the console's current codepage, to avoid mojibake you need to first run `chcp.com [oemcp]` to ensure the console is using the OEM codepage, whatever that is for the current locale. – Eryk Sun Jun 15 '17 at 08:27
0
@echo off
for /f "usebackq delims= skip=1" %%a in (`wmic OS get caption 2^>nul ^| findstr "."`) do set caption=%%a
for /f "usebackq delims=" %%a in (`echo %caption%`) do set caption=%%a
set "caption=%caption:~0,-1%"
echo Caption=[%caption%]
  • 1
    While what you have written may answer the question, it does seem a little lacking in explanation and may illicit confusion to other users. Can you please expand upon your answer so that it is clearer and more accessible? This will make for better answers and help future users understand how the problem was solved. – Andrew Mar 15 '19 at 09:50