batch-filesystem-information

systeminfo - selected fields, write output to csv file


Trying to use systeminfo to pull a couple of pieces of info & write it to an external file.

My command line now is

SYSTEMINFO /S MyComputerName /FO CSV /NH >> sysinfo.csv

let's say to start, I'd like OS name I tried this but not quite working...

SYSTEMINFO /S MyComputerName /FO CSV /NH | findstr "OS\ Name" | findstr /v BIOS >> sysinfo.csv

seems to still be pulling all system info.

I have also used a different version using /c:...

systeminfo|findstr /c:"System Boot Time" /c:"Host Name" /c:"OS Name"

which works to get the info I need, but then adding the switches to format it as csv & output to a file fails with an empty file...

SYSTEMINFO /S MyComputerName /FO CSV /NH|findstr /c:"System Boot Time" /c:"Host Name" /c:"OS Name" /c:"OS Version" >> sysinfo.csv

Any suggestions / corrections? thanks!


Solution

  • SYSTEMINFO has no option to specify which data is wanted in the output. The usage of the option /FO CSV together with the option /H results in all output written into one comma-separated line. FINDSTR cannot be used to filter the CSV data in one line. FINDSTR searches always just for one or more strings in a line and outputs the entire line on having found a matching string. The output is empty as the header information searched for with FINDSTR in last command line are not present at all in the single data row output by SYSTEMINFO.

    The wanted data do not usually contain an exclamation mark, see Naming conventions in Active Directory for computers, domains, sites, and OUs. A computer name can contain ! and can also begin with ; but I have never seen such a computer name. It is in almost all cases possible using the following batch file to get the wanted data.

    @echo off
    setlocal EnableExtensions EnableDelayedExpansion
    set "ComputerData="
    for /F "tokens=1* delims=:" %%G in ('%SystemRoot%\System32\systeminfo.exe /S MyComputerName /FO LIST 2^>nul ^| %SystemRoot%\System32\findstr.exe /B /L /C:"Host Name" /C:"OS Name" /C:"OS Version" /C:"System Boot Time"') do for /F tokens^=^*^ eol^= %%I in ("%%H") do set ComputerData=!ComputerData!,"%%I"
    if defined ComputerData echo !ComputerData:~1!>>sysinfo.csv
    endlocal
    

    The option /S MyComputerName and >>sysinfo.csv instead of >sysinfo.csv makes sense only on embedding the lines 3 to 5 in an outer FOR loop for getting the computer data of multiple computers as shown below. /S MyComputerName should be removed for running this batch file for just the current computer.

    In case of somebody wants to use this code for other data output by SYSTEMINFO which could contain one or more ! as well, the code in the following batch file could be used as template for the task.

    @echo off
    setlocal EnableExtensions DisableDelayedExpansion
    set "ComputerData="
    (for /F "tokens=1* delims=:" %%G in ('%SystemRoot%\System32\systeminfo.exe /FO LIST 2^>nul ^| %SystemRoot%\System32\findstr.exe /B /L /C:"Host Name" /C:"OS Name" /C:"OS Version" /C:"System Boot Time"') do for /F tokens^=^*^ eol^= %%I in ("%%H") do set "CurrentData=%%I" & call :Concatenate) & goto OutputData
    :Concatenate
    set ComputerData=%ComputerData%,"%CurrentData%"& goto :EOF
    :OutputData
    echo %ComputerData:~1%>sysinfo.csv
    endlocal
    

    That slower processed batch file is designed for being used only on current computer. The usage of this code for multiple computers with an outer FOR loop requires some modifications as it can be seen below.

    @echo off
    setlocal EnableExtensions DisableDelayedExpansion
    (for %%# in ("%COMPUTERNAME%" "ComputerName2" "ComputerName3") do (
        set "ComputerData="
        for /F "tokens=1* delims=:" %%G in ('%SystemRoot%\System32\systeminfo.exe /S %%# /FO LIST 2^>nul ^| %SystemRoot%\System32\findstr.exe /B /L /C:"Host Name" /C:"OS Name" /C:"OS Version" /C:"System Boot Time"') do for /F tokens^=^*^ eol^= %%I in ("%%H") do set "CurrentData=%%I" & call :Concatenate
        if defined ComputerData (
            setlocal EnableDelayedExpansion
            echo !ComputerData:~1!
            endlocal
        )
    ))>sysinfo.csv
    endlocal & exit /B 2>nul
    :Concatenate
    set ComputerData=%ComputerData%,"%CurrentData%"& goto :EOF
    

    There can be seen here how to write all data into the output file sysinfo.csv by opening the output file only once before the data is collected, formatted, and output to the file, and finally closing the file.

    The first code with the lines 3 to 5 embedded in an outer FOR loop would open for each computer the output file, seek to end, append the data, and close the file. That is slower and could result in Windows Command Processor failing to re-open the CSV file for appending the next data if another process like an anti-virus program running in background opened the output CSV file in the meantime for scanning it for threads. Here is an example:

    @echo off
    setlocal EnableExtensions EnableDelayedExpansion
    del /A /F "%~dp0sysinfo.csv" 2>nul
    for /F usebackq^ delims^=^ eol^= %%# in ("%~dp0Computer Names List.txt") do (
        set "ComputerData="
        for /F "tokens=1* delims=:" %%G in ('%SystemRoot%\System32\systeminfo.exe /S "%%~#" /FO LIST 2^>nul ^| %SystemRoot%\System32\findstr.exe /B /L /C:"Host Name" /C:"OS Name" /C:"OS Version" /C:"System Boot Time"') do for /F ^tokens^=^*^ eol^= %%I in ("%%H") do set ComputerData=!ComputerData!,"%%I"
        if defined ComputerData echo !ComputerData:~1!>>"%~dp0sysinfo.csv"
    )
    endlocal
    

    Output to the console window like with the following line inside the outer FOR loop to standard output is no problem with this solution.

    echo Processing computer "%%~#" ...
    

    The same code as above with the output optimization as in third solution:

    @echo off
    setlocal EnableExtensions EnableDelayedExpansion
    (for /F usebackq^ delims^=^ eol^= %%# in ("%~dp0Computer Names List.txt") do (
        set "ComputerData="
        for /F "tokens=1* delims=:" %%G in ('%SystemRoot%\System32\systeminfo.exe /S "%%~#" /FO LIST 2^>nul ^| %SystemRoot%\System32\findstr.exe /B /L /C:"Host Name" /C:"OS Name" /C:"OS Version" /C:"System Boot Time"') do for /F tokens^=^*^ eol^= %%I in ("%%H") do set ComputerData=!ComputerData!,"%%I"
        if defined ComputerData echo !ComputerData:~1!
    ))>"%~dp0sysinfo.csv"
    endlocal
    

    A process information to standard output is not possible in this case. But it would be possible to output a process information to standard error for getting it displayed in the console window as shown below.

    echo Processing computer "%%~#" ...>&2
    

    SYSTEMINFO makes something similar. It outputs process information to standard error. That is the reason for using 2^>nul on execution of systeminfo.exe to prevent this process output written to console.

    The last two solutions reference the file with the computer names line by line and the output file with the batch file directory path. The other solutions create the output file in the current working directory which can be any directory on batch file execution.

    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.

    Read the Microsoft documentation about Using command redirection operators for an explanation of | and 2>nul and 1>&2. The redirection operators | and > must be escaped with caret character ^ on FOR command line to be interpreted as literal character when Windows command interpreter processes this command line before executing command FOR which executes the embedded command line with using a separate command process started in background with %ComSpec% /c and the command line within ' appended.

    See single line with multiple commands using Windows batch file for an explanation of the unconditional command operator &. There is no space left to & on the command line with set as that space would be appended by SET to the string value assigned to the environment variable ComputerData.