Reputation: 452
I'm working on batch file and export to text file. Seem all of them is ok, but when i open text file, many new lines break. So, i want to remove of them.
@echo OFF
setlocal EnableDelayedExpansion
(
systeminfo |findstr /c:"Host Name" /c:"OS Name" /c:"OS Version" /c:"Original Install Date" /c:"System Manufacturer" /c:"System Model" /c:"System Type" /c:"Total Physical Memory"
wmic bios get serialnumber /Format:list | more | findstr .
wmic cpu get name /Format:list | more | findstr .
echo=%userdomain%\%username%
)> %ComputerName%.txt
The result text file is ok, but still many new lines break, i want to remove of them
Host Name: PGV-PF165HNN
OS Name: Microsoft Windows 10 Pro
OS Version: 10.0.18363 N/A Build 18363
Original Install Date: 7/22/2019, 6:28:01 PM
System Manufacturer: LENOVO
System Model: 20JM0009US
System Type: x64-based PC
BIOS Version: LENOVO N1QET87W (1.62 ), 2/27/2020
Total Physical Memory: 8,072 MB
SerialNumber=PF165HNN
Name=Intel(R) Core(TM) i5-6300U CPU @ 2.40GHz
WINDOM1\brian.lee
Upvotes: 3
Views: 1726
Reputation: 49086
The OS language dependent output of %SystemRoot%\System32\systeminfo.exe
is character encoded in ASCII/ANSI/OEM which means one byte per character using the code page as displayed on running in a command prompt window chcp
. The code page depends on the country (region) configured for the account used to run the batch file. The code page does not really matter as long as the data of interest do not contain characters with a code value greater 127 (non-ASCII character).
The output of systeminfo
filtered by findstr
is in binary with hexadecimal offset in file left to colon, hexadecimal values of the bytes, and their ASCII representation after the semicolon:
0000h: 48 6F 73 74 20 4E 61 6D 65 3A 20 20 20 20 20 20 ; Host Name:
0010h: 20 20 20 20 20 20 20 20 20 20 20 50 47 56 2D 50 ; PGV-P
0020h: 46 31 36 35 48 4E 4E 0D 0A 4F 53 20 4E 61 6D 65 ; F165HNN..OS Name
0030h: 3A 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 ; :
0040h: 20 20 20 20 4D 69 63 72 6F 73 6F 66 74 20 57 69 ; Microsoft Wi
0050h: 6E 64 6F 77 73 20 31 30 20 50 72 6F 0D 0A 4F 53 ; ndows 10 Pro..OS
0060h: 20 56 65 72 73 69 6F 6E 3A 20 20 20 20 20 20 20 ; Version:
0070h: 20 20 20 20 20 20 20 20 20 31 30 2E 30 2E 31 38 ; 10.0.18
0080h: 33 36 33 20 4E 2F 41 20 42 75 69 6C 64 20 31 38 ; 363 N/A Build 18
0090h: 33 36 33 0D 0A 4F 72 69 67 69 6E 61 6C 20 49 6E ; 363..Original In
00a0h: 73 74 61 6C 6C 20 44 61 74 65 3A 20 20 20 20 20 ; stall Date:
00b0h: 37 2F 32 32 2F 32 30 31 39 2C 20 36 3A 32 38 3A ; 7/22/2019, 6:28:
00c0h: 30 31 20 50 4D 0D 0A 53 79 73 74 65 6D 20 4D 61 ; 01 PM..System Ma
00d0h: 6E 75 66 61 63 74 75 72 65 72 3A 20 20 20 20 20 ; nufacturer:
00e0h: 20 20 4C 45 4E 4F 56 4F 0D 0A 53 79 73 74 65 6D ; LENOVO..System
00f0h: 20 4D 6F 64 65 6C 3A 20 20 20 20 20 20 20 20 20 ; Model:
0100h: 20 20 20 20 20 32 30 4A 4D 30 30 30 39 55 53 0D ; 20JM0009US.
0110h: 0A 53 79 73 74 65 6D 20 54 79 70 65 3A 20 20 20 ; .System Type:
0120h: 20 20 20 20 20 20 20 20 20 20 20 20 78 36 34 2D ; x64-
0130h: 62 61 73 65 64 20 50 43 0D 0A 42 49 4F 53 20 56 ; based PC..BIOS V
0140h: 65 72 73 69 6F 6E 3A 20 20 20 20 20 20 20 20 20 ; ersion:
0150h: 20 20 20 20 20 4C 45 4E 4F 56 4F 20 4E 31 51 45 ; LENOVO N1QE
0160h: 54 38 37 57 20 28 31 2E 36 32 20 29 2C 20 32 2F ; T87W (1.62 ), 2/
0170h: 32 37 2F 32 30 32 30 0D 0A 54 6F 74 61 6C 20 50 ; 27/2020..Total P
0180h: 68 79 73 69 63 61 6C 20 4D 65 6D 6F 72 79 3A 20 ; hysical Memory:
0190h: 20 20 20 20 38 2C 30 37 32 20 4D 42 0D 0A ; 8,072 MB..
The output of %SystemRoot%\System32\wbem\wmic.exe
is always Unicode encoded using UTF-16 Little Endian encoding with byte order mark (BOM). So the output by the two used wmic
command lines is with two bytes per character.
The command line wmic bios get serialnumber /Format:list
produces in binary the output:
0000h: FF FE 0D 00 0A 00 0D 00 0A 00 53 00 65 00 72 00 ; ÿþ........S.e.r.
0010h: 69 00 61 00 6C 00 4E 00 75 00 6D 00 62 00 65 00 ; i.a.l.N.u.m.b.e.
0020h: 72 00 3D 00 50 00 46 00 31 00 36 00 35 00 48 00 ; r.=.P.F.1.6.5.H.
0030h: 4E 00 4E 00 0D 00 0A 00 0D 00 0A 00 0D 00 0A 00 ; N.N.............
The first two bytes FF FE
is the byte order mark for UTF-16 Little Endian. Each ASCII character is encoded with two bytes (16 bits) with high byte having value 0. The newline characters are carriage return (0D 00) and line-feed (0A 00). There are two empty lines output first, then the line with the data of interest, and finally once again two empty lines.
The command line wmic cpu get name
produces in binary the output:
0000h: FF FE 0D 00 0A 00 0D 00 0A 00 4E 00 61 00 6D 00 ; ÿþ........N.a.m.
0010h: 65 00 3D 00 49 00 6E 00 74 00 65 00 6C 00 28 00 ; e.=.I.n.t.e.l.(.
0020h: 52 00 29 00 20 00 43 00 6F 00 72 00 65 00 28 00 ; R.). .C.o.r.e.(.
0030h: 54 00 4D 00 29 00 20 00 69 00 35 00 2D 00 36 00 ; T.M.). .i.5.-.6.
0040h: 33 00 30 00 30 00 55 00 20 00 43 00 50 00 55 00 ; 3.0.0.U. .C.P.U.
0050h: 20 00 40 00 20 00 32 00 2E 00 34 00 30 00 47 00 ; .@. .2...4.0.G.
0060h: 48 00 7A 00 0D 00 0A 00 0D 00 0A 00 0D 00 0A 00 ; H.z.............
The Unicode output is redirected by cmd.exe
processing the batch file to more
which outputs the lines now with one byte per character. But Windows command processor has a bug on interpreting UTF-16 LE encoded lines as it can be seen on using the following command line:
wmic bios get serialnumber /Format:list | more >output.txt
The file output.txt
contains the binary bytes:
0000h: 0D 0D 0A 0D 0D 0A 53 65 72 69 61 6C 4E 75 6D 62 ; ......SerialNumb
0010h: 65 72 3D 50 46 31 36 35 48 4E 4E 0D 0D 0A 0D 0D ; er=PF165HNN.....
0020h: 0A 0D 0D 0A 0D 0A 0D 0A ; ........
Each Unicode encoded carriage return + line-feed (0D 00 0A 00) becomes ASCII encoded carriage return + carriage return + line-feed (0D 0D 0A).
That is the real problem here. The additional carriage return results on using regular expression search string .
to match all lines with at least one character that also the empty lines are matched by this regular expression search string on output converted not correct from Unicode to ASCII.
It depends on used text editor how the not valid sequence of newline characters are interpreted. Most text editors interpret the carriage return without line-feed as line termination, but findstr
does not do that.
One solution is explicitly searching for the line which contains the data of interest.
@echo off
setlocal EnableExtensions DisableDelayedExpansion
(
%SystemRoot%\System32\systeminfo.exe | %SystemRoot%\System32\findstr.exe /L /C:"Host Name" /C:"OS Name" /C:"OS Version" /C:"Original Install Date" /C:"System Manufacturer" /C:"System Model" /C:"System Type" /C:"Total Physical Memory"
%SystemRoot%\System32\wbem\wmic.exe BIOS GET SerialNumber /VALUE | %SystemRoot%\System32\findstr.exe /L /C:SerialNumber
%SystemRoot%\System32\wbem\wmic.exe CPU GET Name /VALUE | %SystemRoot%\System32\findstr.exe /L /C:Name
echo %USERDOMAIN%\%USERNAME%
) >"%ComputerName%.txt"
endlocal
The data written into file %ComputerName%.txt
is completely encoded in ASCII with everywhere used just 0D 0A
as line termination.
Some additional information about small changes on code:
more
is omitted as not really necessary. The not correct conversion from Unicode to ASCII is done by Windows command processor cmd.exe
.cmd.exe
has not to search for the executables using the values of the environment variables PATHEXT
and PATH
./Format:list
is replaced by option /VALUE
which results in same output./L
to explicitly instruct findstr
to run a literal search although that is the default on using option /C:
.An even better batch file code would be:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
(
%SystemRoot%\System32\systeminfo.exe | %SystemRoot%\System32\findstr.exe /L /C:"Host Name" /C:"OS Name" /C:"OS Version" /C:"Original Install Date" /C:"System Manufacturer" /C:"System Model" /C:"System Type" /C:"Total Physical Memory"
for /F "tokens=1* delims==" %%I in ('%SystemRoot%\System32\wbem\wmic.exe BIOS GET SerialNumber /VALUE') do if not "%%J" == "" echo Serial Number: %%J
for /F "tokens=1* delims==" %%I in ('%SystemRoot%\System32\wbem\wmic.exe CPU GET Name /VALUE') do if not "%%J" == "" echo CPU Name: %%J
echo Domain\User Name: %USERDOMAIN%\%USERNAME%
) >"%ComputerName%.txt"
endlocal
The additional data determined with WMIC and output with ECHO are written into the text file in same format as the output of systeminfo
.
Attention: The last echo
command line is not safe in case of value of environment variable USERDOMAIN
or of environment variable USERNAME
contains )
or &
. 100% safe would be:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
(
%SystemRoot%\System32\systeminfo.exe | %SystemRoot%\System32\findstr.exe /L /C:"Host Name" /C:"OS Name" /C:"OS Version" /C:"Original Install Date" /C:"System Manufacturer" /C:"System Model" /C:"System Type" /C:"Total Physical Memory"
for /F "tokens=1* delims==" %%I in ('%SystemRoot%\System32\wbem\wmic.exe BIOS GET SerialNumber /VALUE') do if not "%%J" == "" echo Serial Number: %%J
for /F "tokens=1* delims==" %%I in ('%SystemRoot%\System32\wbem\wmic.exe CPU GET Name /VALUE') do if not "%%J" == "" echo CPU Name: %%J
) >"%ComputerName%.txt"
setlocal EnableDelayedExpansion
echo Domain\User Name: !USERDOMAIN!\!USERNAME!>>"%ComputerName%.txt"
endlocal
endlocal
To understand the commands used and how they work, open a command prompt window, execute there the following commands, and read the displayed help pages for each command, entirely and carefully.
echo /?
endlocal /?
findstr /?
for /?
if /?
setlocal /?
systeminfo /?
wmic /?
wmic bios /?
wmic bios get /?
wmic cpu /?
wmic cpu get /?
Upvotes: 3
Reputation: 2565
Just an alternative way without using DisableDelayedExpansion
:
@echo off && setlocal EnableDelayedExpansion
set "_usrd=Domain\User Name: !USERDOMAIN!\!USERNAME!" && set "_bios=Bios Serial Number: -x" && set "_CPUs=CPU Name: -y"
set "_wmic=%SystemRoot%\System32\wbem\wmic.exe" && pushd "%SystemRoot%\System32" && >"%temp%\%ComputerName%.txt" 2>nul (
systeminfo.exe | findstr "Host.Name OS.Name OS.Version Original.Install.Date System.Manufacturer System.Model System.Type Total.Physical.Memory"
for /f skip^=1^tokens^=* %%i in ('!_wmic! bios get serialnumber^|findstr "[0-9] [aZ]"')do ^< nul call set /p "'=!_bios:-x= %%~i!" <nul & echo\
for /f skip^=1^tokens^=* %%j in ('!_wmic! cpu get name^|findstr "[0-9] [aZ]"')do ^< nul call set /p "'=!_CPUs:-y= %%~j!" <nul & echo\
echo\!_usrd! ) && type "%temp%\%ComputerName%.txt" && popd && endlocal && goto :EOF
Host Name: LAME_SLUG
OS Name: Microsoft Windows 10 Pro
OS Version: 10.0.18363 N/A Build 18363
Original Install Date: 3/27/2020, 11:17:06 PM
System Manufacturer: LENOVO
System Model: 80YH
System Type: x64-based PC
BIOS Version: LENOVO 4WCN46WW, 12/30/2019
Total Physical Memory: 16,259 MB
Bios Serial Number: PE03A187
CPU Name: Intel(R) Core(TM) i7-7500U CPU @ 2.70GHz
Domain\User Name: LAME_SLUG\ecker
Upvotes: 1
Reputation: 140
can you try this: create a sysi.vbs file with the following code and run this way: cscript //nologo sysi.vbs
adjust as you needs.
sysi.vbs: '---------------------------------------------
Set dtmConvertedDate = CreateObject("WbemScripting.SWbemDateTime")
strComputer = "."
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colOperatingSystems = objWMIService.ExecQuery ("Select * from Win32_OperatingSystem")
' Create a new WshNetwork object to access network properties.
Wscript.Echo "*** from WScript.Network ***************"
Set WshNetwork = WScript.CreateObject("WScript.Network")
Wscript.Echo "Computer name : " & WshNetwork.ComputerName
Wscript.Echo "Domain : " & WshNetwork.UserDomain
Wscript.Echo "User name : " & WshNetwork.UserName
Wscript.Echo "*** from Win32_OperatingSystem **************"
For Each objOperatingSystem in colOperatingSystems
Wscript.Echo "OS Caption: " & objOperatingSystem.Caption
Wscript.Echo "OS Version: " & objOperatingSystem.Version
dtmConvertedDate.Value = objOperatingSystem.InstallDate
dtmInstallDate = dtmConvertedDate.GetVarDate
Wscript.Echo "OS Install Date: " & dtmInstallDate
Wscript.Echo "OS Serial Number: " & objOperatingSystem.SerialNumber
Next
Set colItems = objWMIService.ExecQuery("Select * from Win32_ComputerSystem",,48)
Wscript.Echo "*** from Win32_ComputerSystem **********"
For Each objItem in colItems
Wscript.Echo "Manufacturer: " & objItem.Manufacturer
Wscript.Echo "Model: " & objItem.Model
Wscript.Echo "SystemType: " & objItem.SystemType
Wscript.Echo "TotalPhysicalMemory: " & objItem.TotalPhysicalMemory
Next
Wscript.Echo "*** from Win32_Processor **********"
Set colItems = objWMIService.ExecQuery("Select * from Win32_Processor",,48)
For Each objItem in colItems
Wscript.Echo "Proc Name: " & objItem.Name
Wscript.Echo "CurrentClockSpeed: " & objItem.CurrentClockSpeed
Wscript.Echo "ErrorDescription: " & objItem.ErrorDescription
Wscript.Echo "DeviceID: " & objItem.DeviceID
Wscript.Echo "Manufacturer: " & objItem.Manufacturer
Wscript.Echo "MaxClockSpeed: " & objItem.MaxClockSpeed
Next
Wscript.Echo "*** from Win32_BIOS ******* "
Set colBIOS = objWMIService.ExecQuery("Select * from Win32_BIOS")
Set dtmRelDateRaw = CreateObject("WbemScripting.SWbemDateTime")
For each objBIOS in colBIOS
Wscript.Echo "BIOS Name: " & objBIOS.Name
Wscript.Echo "BIOS Manufacturer: " & objBIOS.Manufacturer
Wscript.Echo "Primary BIOS: " & objBIOS.PrimaryBIOS
dtmRelDateRaw.Value = objBIOS.ReleaseDate
dtmRelDate = dtmRelDateRaw.GetVarDate
Wscript.Echo "Release Date: " & objBIOS.ReleaseDate
Wscript.Echo "Release Date: " & dtmRelDate
Wscript.Echo "Serial Number: " & objBIOS.SerialNumber
Wscript.Echo "Status: " & objBIOS.Status
Wscript.Echo "Version: " & objBIOS.Version
Next
Upvotes: 1