Search code examples
cmdwmic

Remove space at last Property value of WMIC and add another string


Sorry for my bad English. I want to remove space at the last Property value of WMIC and add another string.

del /f /q "GPU.txt"
for /f "skip=2 tokens=2,3,4 delims=," %%a in ('"wmic path Win32_VideoController get Caption,CurrentHorizontalResolution,CurrentVerticalResolution /format:csv"') do (
    SETLOCAL EnableDelayedExpansion
    For %%# in (*) do (
        SET var=%%~n#
        Set MyVar=!var!
        set MyVar=!MyVar: =!
    )
    echo %%a (%%b x !MyVar!)>>"GPU.txt"
)

Nothing to display. Thanks.


Solution

  • Why does the code in question not work?

    1. Please read this answer for details about the commands SETLOCAL and ENDLOCAL. On using SETLOCAL inside a FOR loop it is highly recommended to use also ENDLOCAL in same FOR loop or a stack overflow could occur during execution of the loop. This does not occur here because there are not many loop iterations, but ENDLOCAL should be used nevertheless in same FOR loop containing also SETLOCAL.

    2. For %%# in (*) do in code of question processes each file name of non-hidden files in current directory. The file name without file extension is assigned to environment variable var. Next this variable is assigned to another variable MyVar without any modification, except the line Set MyVar=!var! would contain trailing spaces or tabs. And last all spaces are removed from string value of environment variable MyVar which is a file name.

      I have no idea what this FOR loop for processing file names in current directory has to do with name of video controller and current horizontal and vertical resolution.

      I recommend reading answer on Why is no string output with 'echo %var%' after using 'set var = text' on command line?

    3. The closing round bracket ) in command line echo %%a (%%b x !MyVar!)>>"GPU.txt" is interpreted as end of command block of first FOR. It would be necessary to escape ) with ^ and use echo %%a (%%b x !MyVar!^)>>"GPU.txt" to get closing parenthesis interpreted by cmd.exe as literal character to output by echo on parsing the entire command block starting with ( on first FOR command line.

    4. wmic.exe outputs the text UTF-16 Little Endian (two bytes per character) instead of ANSI encoded (one byte per character). FOR respectively cmd.exe has a bug on interpreting the Unicode encoded character stream as explained for example in detail at How to correct variable overwriting misbehavior when parsing output?

      What you think is a space at end of vertical resolution value is in real a carriage return appended to this value because of wrong processing of Unicode output of wmic.exe by command FOR respectively cmd.exe.

    What is a working code and why does it work?

    One possible solution for this task is using this batch code:

    @echo off
    setlocal EnableExtensions DisableDelayedExpansion
    (for /F "tokens=2-4 delims=," %%I in ('%SystemRoot%\System32\wbem\wmic.exe PATH Win32_VideoController GET Caption^,CurrentHorizontalResolution^,CurrentVerticalResolution /FORMAT:CSV ^| %SystemRoot%\System32\findstr.exe /R ",[0123456789][0123456789]*$"') do (
        set /A CurrentVerticalResolution=%%K
        call echo %%I (%%J x %%CurrentVerticalResolution%%^)
    ))>"GPU.txt"
    endlocal
    

    The Unicode output of Windows Management Instrumentation Command is redirected to FINDSTR which filters the output on lines ending with a comma and one or more digits. So heading line of CSV output is removed and also video controller lines ending with ,, without values for current horizontal and vertical resolution. Such a CSV line is output also on my Windows computer in addition to the CSV line with the correct values.

    The problem with wrong carriage return at end of last value of current vertical resolution remains despite filtering output of wmic.exe with findstr.exe.

    For that reason the current vertical resolution value assigned to loop variable K is not used directly in echo command line because this would result in ) overwriting first character of video controller caption string. The solution used here is using an arithmetic expression to assign the current vertical resolution value to the environment variable CurrentVerticalResolution. The carriage return at end of the integer value is interpreted like any other whitespace character at end of an expression on evaluation of the arithmetic expression which means it is ignored by cmd.exe. So environment variable CurrentVerticalResolution has assigned the value without the unwanted carriage return at end.

    The code above avoids usage of SETLOCAL and ENDLOCAL by using command CALL to parse the echo command line twice as explained by:

    How does the Windows Command Interpreter (CMD.EXE) parse scripts?

    The echo command line with escaped ) and with %%CurrentVerticalResolution%% instead of %CurrentVerticalResolution% is already modified to the line below on first parsing the echo command line by cmd.exe before executing command FOR:

    call echo %I (%J x %CurrentVerticalResolution%)
    

    The remaining environment variable reference %CurrentVerticalResolution% is replaced by current value of this environment variable before executing command ECHO on second parsing on each iteration of the loop because of command CALL.

    It would be also possible to use inside the FOR loop:

    setlocal EnableDelayedExpansion
    echo %%I (%%J x !CurrentVerticalResolution!^)
    endlocal