0

I have a task to query some hostnames for their serial number stored in the BIOS. I have the hostnames in a text file gets processed with a for loop, the clients are queried for the serial number with another for loop, and the result is directed into another text file.

This works no problem if the host is offline or doesn't respond. The hostname is written to the text file and the serial number is blank, and the script then moves on to the next entry in the input file. But if the host responds and a serial number is stored in the variable, the script initially writes to the output file as it should, but then it writes another line with the same hostname and a blank serial number before moving onto the next line in the input file.

@ECHO OFF

set list=c:\temp\input.txt

for /F %%C in (%list%) do (
    for /F "skip=1" %%S in ('wmic /node:%%C bios get serialnumber') do ( 
        echo %%C - %%S >>c:\temp\output.txt)
    )

pause

This results in output that looks like this:

DC6068WA00829 -  
DC6054WA00178 -  
DC6061WA00065 - R93NSI3
DC6061WA00065 -  
DC6061WA00064 - R0KBN3S
DC6061WA00064 -  
DC6023LA034284 -  
DC6038LA034272 -  

As you can see, when the host doesn't respond because it's offline or can't be contacted for whatever reason, it moves on to the next one just as it should. But when one responds, it immediately writes another line with just the hostname and a dash.

I've tried making the write command to the output file as a separate subroutine call, I've tried removing the writing of the %%S variable to see if that was interfering in some way, I've tried saving the results to different variables before outputting them to the file, but nothing makes any difference.

I can clean up the resulting file without too much issue. I mostly just want to know what I'm missing that would be causing this to happen.

Any help or insight would be appreciated.

2
  • 1
    The /FailFast, (which is Off by default), can be used. It will ping each node and only send the WMI commands to those which respond, i.e. WMIC /Node:@%%C /FailFast:On BIOS "Where SerialNumber Is Not Null" Get SerialNumber. Commented Apr 23, 2019 at 9:49
  • Thanks, I didn't know about /FailFast. That speeds it up quite a bit. Commented Apr 23, 2019 at 16:35

2 Answers 2

2

You will notice that when you run by itself:

wmic /node:somehostname bios get serialnumber

It still has Unicode cr/lf characters, which you cannot see on cmd prompt terminal as they are displayed as empty lines. This however causes the characters to be assigned to the %%C meta variable and run the loop again on these characters, will display both the entries in your file.. Instead, we check if a variable exists and create it if not, which will ensure we only assign the actual value. Note, we are using delayedexpansion here as we are setting and using variables inside of a code block.

@echo off
setlocal enabledelayedexpansion
set "list=C:\temp\input.txt"

type nul>"C:\Temp\output.txt"
for /F %%C in (%list%) do (
    for /F "skip=1" %%S in ('wmic /node:%%C bios get serialnumber') do if not defined serial set "serial=%%C - %%S"
        echo(!serial!>>"C:\temp\output.txt"
)
type output.txt
pause

Note

I created type nul>"C:\Temp\output.txt" to ensure we do not append to previous runs of the script, if you want it to append, then remove that line.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, this helped immensely. I did have to make a small change because the serial variable was not updating and was just outputting the first entry for every line, no matter if it received a successful response or not. I just changed it to echo(!serial!>>"C:\temp\output.txt" & set serial= to clear the variable before it restarts the loop. Now it's working exactly as I expected it to. Thank you!
0
  • wmic.exe output is crippled with the unusual line ending cr/cr/lf,
    resulting from an erroneous unicode conversion.
  • for /f would skip empty lines, but can't with those cr/cr/lf sequences
    so these lines with just the %%C are output.
  • one solution is another for parsing the uppercase %%S with %%s
  • technically all the for /f are one line:

:: Q:\Test\2019\04\23\SO_55804785.cmd
@ECHO OFF
set "FileIn=c:\temp\input.txt"
set "FileOut=c:\temp\output.txt"

for /F "usebackq delims=" %%C in (
    "%FileIn%"
) do for /F "skip=1 delims=" %%S in (
    'wmic /node:%%C bios get serialnumber 2^>Nul ^|findstr "^." '
) do for /F "delims=" %%s in (
    "%%S"
) do echo %%C - %%s >>"%FileOut%"

pause

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.