Search code examples
parsingbatch-filenetstat

Parsing NETSTAT -ban switches in batch


Extensive searches found no solution in batch to parse netstat -bano (same switch as -nab, -bna, -anb, -nba, nabo, etc.) so all info from a given network connection is on the same line.

Netstat's -ban switches are used to:

-b = display executable

-a = display all connections and listening ports

-n = display addresses and ports in numerical form.

-o = display owning process ID for each connection (i.e., PID)

But netstat adds the file name to the next line, making processing the output very difficult. Extensive searches didn't find any answers in batch.

I created a way to parse it by looking for a ] (right bracket) as the last character on a line. If it is a ], then basically output the "combined" line, which now contains the executable.

My code is posted as an answer, but does an ugly job since it has to use files to handle the parsing instead of variables.


Solution

  • Created solution in batch to concatenate all output for a given connection so it's on one line. Save script (below) as a batch file and when run it will create a file called "NETSTAT--%computername%.txt" in the same folder as the script, where %computername% will be replaced with the hostname of computer it's run on.

    @ECHO OFF
    SetLocal
    REM Method of finding last character-of-a-string-from-a-variable
    REM http://stackoverflow.com/a/15662607/1569434
    
    REM Get the script's path so all needed files can sit in the same folder
    SET SCRIPTPATH=%~p0
    CD %SCRIPTPATH%
    
    REM Read and pass each line in file one at a time to sub 'FindEXE'
    SET CONCATLINE=
    SET HEADERROW=
    SET /A LINECOUNT = 0
    @echo LINECOUNT = %LINECOUNT%
    del %SCRIPTPATH%\netstat*.txt /q 2>nul
    
    netstat -bano>%SCRIPTPATH%\netstat0.txt
    REM Copy all lines except those with "TIME_WAIT" into text file
    FINDSTR /V /I /C:"TIME_WAIT" %SCRIPTPATH%\netstat0.txt>%SCRIPTPATH%\netstat1.txt
    REM Delete first two lines, which are a header and a blank line
    for /f "skip=2 delims=*" %%a in (%SCRIPTPATH%\netstat1.txt) do (echo %%a>>%SCRIPTPATH%\netstat2.txt)
    
    REM Search for and process file based on matching text
    REM This sub begins putting each netstat connection on one line
    for /f "delims=*" %%A in (%SCRIPTPATH%\netstat2.txt) do call :FindTXT1 %%A
    
    REM netstat3 will have all data from given connection on one line
    SET /A LINECOUNT = 0
    for /f "delims=*" %%A in (%SCRIPTPATH%\netstat3.txt) do call :FindTXT2 %%A
    
    REM Keep only header and unique (i.e., those with "[::]") 'listening' connections
    FINDSTR /I /C:"LISTENING" /C:"Local Address" %SCRIPTPATH%\netstat4.TXT>%SCRIPTPATH%\netstat5.TXT
    FINDSTR /I /C:"[::]:" /C:"Local Address" %SCRIPTPATH%\netstat5.TXT>%SCRIPTPATH%\netstat6.TXT
    
    MOVE /Y %SCRIPTPATH%\netstat6.txt %SCRIPTPATH%\NETSTAT--%computername%.txt
    del %SCRIPTPATH%netstat*.txt /q 2>nul
    @echo off
    
    echo done.
    
    EndLocal
    goto :EOF
    
    
    
    
    :FindTXT1
    REM We've got a line sent to us. Set variable to entire line using * (instead of %1)
    SET CURRENTLINE=%*
    SET /A LINECOUNT = %LINECOUNT% + 1
    REM Add line feed after header row and return to main script
    IF "%LINECOUNT%" == "1" (
        SET HEADERROW=%CURRENTLINE%
        @ECHO %CURRENTLINE%> %SCRIPTPATH%\netstat3.txt
        goto :eof
        )
    
    REM Append a comma and CURRENTLINE to CONCATLINE. NOTE: Script expecting comma; don't use semi-colon
    SET CONCATLINE=%CONCATLINE%,%CURRENTLINE%
    
    REM When echo line, remove first char (comma, inserted above) using:
    REM http://ss64.com/nt/syntax-substring.html
    REM If last char is "]" then print, otherwise append
    IF "%CURRENTLINE:~-1%"=="]" (
        REM @echo right bracket=FOUND
        @echo %CONCATLINE:~1%>>%SCRIPTPATH%\netstat3.txt
        SET CONCATLINE=
            ) else (
        REM @echo right bracket=NOT found
        )
    
    REM If line = "Can not obtain ownership information" then print, otherwise append
    IF "%CURRENTLINE%"=="Can not obtain ownership information" (
        REM @echo No Ownership=TRUE
        @echo %CONCATLINE:~1%>>%SCRIPTPATH%\netstat3.txt
        SET CONCATLINE=
        )
    
    goto :eof
    
    
    :FindTXT2
    REM We've got a line sent to us. Set variable to entire line using * (instead of %1)
    SET CURRENTLINE=%*
    SET /A LINECOUNT = %LINECOUNT% + 1
    REM Add line feed after header row and return to main script
    IF "%LINECOUNT%" == "1" (
        SET HEADERROW=%CURRENTLINE%
        @ECHO %CURRENTLINE%> %SCRIPTPATH%\netstat4.txt
        goto :eof
        )
    
    REM If last char is "]" then search, otherwise append.
    REM Without "DelayedExp...", variable sets to value from previous FOR loop
    IF "%CURRENTLINE:~-1%"=="]" (
        SetLocal ENABLEDELAYEDEXPANSION
        REM IP6 EXEs result in 3 sets of [], so find and set var to last one, which is where EXE lives
        FOR /f "tokens=1,2,3,4,5,6 delims=[]" %%a in ("%CURRENTLINE%") do (
            SET BINNAME1=%%b
            SET BINNAME2=%%f
            IF "!BINNAME1!" == "::" (
                REM @ECHO BINNAME1=!BINNAME1!>>%SCRIPTPATH%\netstat4.txt
                SET BINNAME=!BINNAME2!
                REM @echo %CURRENTLINE%;BINNAME=!BINNAME2!>>%SCRIPTPATH%\netstat4.txt
                ) else (
                SET BINNAME=!BINNAME1!
                REM @echo %CURRENTLINE%;BINNAME=!BINNAME1!>>%SCRIPTPATH%\netstat4.txt
                )
            @echo %CURRENTLINE%;BINNAME=!BINNAME!>>%SCRIPTPATH%\netstat4.txt
            )
        ) else (
        @echo %CURRENTLINE%>>%SCRIPTPATH%\netstat4.txt
        SetLocal DISABLEDELAYEDEXPANSION
    )
    
    goto :eof