1

All;

I've been all around the Internet throughout the day, trying to get a batch file written/working.

Just to start off - I am looking to make this work ONLY via a batch file and/or command line.

I'm looking to remove a specific data (not case-sensitive - as in the data could be 'data' or 'Data' or 'DATA').

Most of the OS's that I've seen the actual data to be on are Win XP machines. The specific's are as follows:

I'm looking to specifically remove the data "browser" (again, it could also be "Browser" or "BROWSER) from a REG_MULTI_SZ registry value, which the subkey is found at:

HKLM\SYSTEM\CurrentControlSet\Services\lanmanserver\parameters

The actual value is:

NullSessionPipes

I've always seen multiple pieces of data within this value (with "browser" being somewhere in the mix). Whether browser is the only piece of data in the value, or multiple pieces of data, I need to be able to execute a .bat in order to remove this.

My research points me to querying the data, removing the "browser" data, then re-inserting the remaining - I'm just not able to successfully do this.

I've attempted to just create a dummy Test key/value on my machine (Win10) at the following:

HKCU\Temp\Test

which contains the data of:

Test #1
Test #2
browser
Browser
BROWSER
Test #3
Test #4

Everything I've done, I've been unable to remove only/any form of browser from this data, leaving the rest of the "Test #x" data's.

Please advise on any solution(s) that anyone can come up with.

UPDATE Here is the code(s) that I've been able to put together throughout my research on this (I have put together several different batch files, without positive results): (NOTE: I in no way take credit for any of this code, as the majority of it has been compiled from/across many different locations):

Test1.bat

This test kept deleting the entire value, which I could not figure out.

    @echo off
    for /f "tokens=*" %%a in ('
        reg query "HKCU\Temp" /v "Test" /f "browser\0Browser\0BROWSER" /d /e
        ^| find "REG_MULTI_SZ"
    ') do (
        setlocal enableDelayedExpansion

        rem Split
        set "line=%%a"
        set "value=!line:*REG_MULTI_SZ=REG_MULTI_SZ!"
        call set "name=%%line:!value!=%%"

        rem Trim spaces
        for /L %%b in (1,1,10) do if "!name:~-1!"==" " set "name=!name:~0,-1!"

        echo Deleting !name!
        reg delete "HKCU\Temp" /v "!name!" /f

        endlocal
    )
    pause

Test2.bat

This was an attempt to export the data into a txt file, then remove "browser" - another failed attempt.

    @echo off
    reg query HKCU\Temp /v Test > c:\Temp\tmp01.txt
    FOR /F "tokens=2,3*" %%a in (c:\Temp\tmp01.txt) do call :sub1 %%b

    :sub1
    if %1x==browser goto end
    echo %1
    REG ADD HKCU\Temp /f /v Test /t REG_MULTI_SZ /d %1\0\0\0
    :end
    goto :eof

Test3.bat

This attempt ended up replacing all data with "%b" for my 'Test' value

    @echo off & setlocal ENABLEEXTENSIONS
    set k="HKCU\Temp"
    set v="Test"
    for /f "tokens=*" %%a in ('reg query %k% /v %v%') do (
    set "d=%%b"
    )
    set "d=%d:browser\0=%"
    set "d=%d:\0\0=%"
    reg add %k% /v %v% /t REG_MULTI_SZ /d "%d%" /f

I did come across some topics where users had stated that if the data was translated to HEX/binary, that this would be easier done? I hope this helps to give some idea to someone as to what exactly I'm doing wrong here.

Kachar
  • 13
  • 5

2 Answers2

0

Here is a commented batch file for this task:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
for /F "skip=2 tokens=1,2*" %%A in ('%SystemRoot%\System32\reg.exe query HKLM\SYSTEM\CurrentControlSet\Services\lanmanserver\parameters /v NullSessionPipes 2^>nul') do if /I "%%A" == "NullSessionPipes" if "%%B" == "REG_MULTI_SZ" set "NullSessionPipes=%%C" & goto ProcessValue
echo Registry value NullSessionPipes was not found in registry.
goto EndBatch

rem The goal is to remove all ENTIRE strings BROWSER written in any case.
rem Other strings containing by chance also BROWSER at beginning or end
rem of the string should not be removed from multi-string value. For that
rem reason run case-insensitive string substitution with \0browser\0 to
rem really match entire BROWSER string. But there can be multiple BROWSER
rem strings in sequence which are not all removed with one run on using
rem \0browser\0 and so a loop is required make the string substitution
rem with \0browser\0 until this string is not removed anymore from value.

rem But BROWSER could be exist also as first string in value with no
rem preceding \0. For that reason \0 is extra added at beginning and
rem then removed after removing all entire BROWSER strings.

rem REG ADD requires that there is no \0\0 at end of multi-string value
rem to successfully add the multi-string value to Windows registry. The
rem data must end with last character of last string or with just \0.
rem For that reason the last two characters being \0 on Windows XP and
rem Windows Server 2003 are removed before even starting processing the
rem multi-string value. REG of Windows Vista and later Windows versions
rem does not output multi-string value with \0\0 at end like REG of
rem Windows XP. It outputs the multi-string with no \0 at end. So it
rem is necessary to append \0 at end in case of last string is BROWSER.

rem It is also necessary to do nothing if the NullSessionPipes value exists
rem with no string resulting on Windows Vista and later Windows version in
rem nothing assigned to NullSessionPipes and so the environment variable
rem does not exit at all. On Windows XP is assigned in this case just \0
rem which on further processing results also in an empty string and
rem therefore deletion of environment variable NullSessionPipes after
rem removing this final end of multi-string marker.

rem On Windows Vista and later Windows versions it is also necessary to
rem append \0 at end of environment variable string as otherwise with an
rem existing string ending by chance with a backslash this backslash would
rem be interpreted by REG as escape character for the double quote used to
rem enclose the data argument string on command line in double quotes on
rem adding the final multi-line string value. So without appending \0 at
rem end string like TEST\ as last string of NullSessionPipes value would
rem become TEST" which of course is not wanted avoided by using TEST\\0
rem at end of environment variable string for this use case.

rem After removing all entire BROWSER strings from value it is checked
rem if the new value is not identical to value read from registry which
rem means at least one BROWSER string was really removed and so it is
rem necessary to write new value without BROWSER back to Windows registry.

:ProcessValue
if "%NullSessionPipes%" == "" goto EndBatch

if "%NullSessionPipes:~-2%" == "\0" set "NullSessionPipes=%NullSessionPipes:~0,-2%"
if "%NullSessionPipes%" == "" goto EndBatch

if not "%NullSessionPipes:~-2%" == "\0" set "NullSessionPipes=%NullSessionPipes%\0"
set "NewSessionPipes=\0%NullSessionPipes%"

:RemoveBrowser
set "TmpSessionPipes=%NewSessionPipes:\0browser\0=\0%"
if not "%TmpSessionPipes%" == "%NewSessionPipes%" set "NewSessionPipes=%TmpSessionPipes%" & goto RemoveBrowser
set "NewSessionPipes=%TmpSessionPipes:~2%"

if "%NewSessionPipes%" == "%NullSessionPipes%" echo Current NullSessionPipes value does not contain the string BROWSER.& goto EndBatch

echo Current NullSessionPipes value is:
echo/
echo %NullSessionPipes%
echo/
echo New NullSessionPipes value is:
echo/
echo %NewSessionPipes%
echo/
%SystemRoot%\System32\reg.exe add HKLM\SYSTEM\CurrentControlSet\Services\lanmanserver\parameters /v NullSessionPipes /t REG_MULTI_SZ /d "%NewSessionPipes%"

:EndBatch
endlocal

The output of the command line

C:\Windows\System32\reg.exe query HKLM\SYSTEM\CurrentControlSet\Services\lanmanserver\parameters /v NullSessionPipes 2>nul

executed by FOR in a separate command process started with cmd /C in background depends on version of REG.

On Windows Vista and Windows Server 2008 and all later Windows versions the output starts with an empty line, second line is the registry key, and third line contains registry value name, value type and the value data separated by spaces.

On Windows XP and Windows Server 2003 the output starts with an empty line, next version of REG, one more empty line, fourth line contains registry key and fifth line finally contains registry value name, value type and the value data with four indent spaces and separated by a horizontal tab character.

So from different output of REG it is possible only to skip the first two lines. The next line contains the data of interest on Windows Vista/Server 2008 and all later versions of Windows. But on Windows XP and Server 2003 it is necessary to process more lines from captured REG output until fifth line is reached with the data of interest. For that reason the two additional IF conditions are used to be 100% sure that the multi-string value of registry value NullSessionPipes is really assigned to environment variable NullSessionPipes before exiting the loop and processing the value.

Output of REG on Windows XP with NullSessionPipes existing but not containing any string:

 
! REG.EXE VERSION 3.0
 
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\lanmanserver\parameters
····NullSessionPipes»   REG_MULTI_SZ»   \0

· in output example above and all others below represents an indenting/separating space character. » represents a separating horizontal tab character.

Output of REG on Windows XP with NullSessionPipes existing but not containing any string:

 
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\lanmanserver\parameters
····NullSessionPipes····REG_MULTI_SZ····

Example output of REG on Windows XP with NullSessionPipes containing strings:

 
! REG.EXE VERSION 3.0
 
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\lanmanserver\parameters
····NullSessionPipes»   REG_MULTI_SZ»   browser\0test #1\0BROWSER\0Browser\0Test\#2\0TEST\\0browser\0\0

Example output of REG on Windows 7 with NullSessionPipes containing strings:

 
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\lanmanserver\parameters
····NullSessionPipes····REG_MULTI_SZ····browser\0test #1\0BROWSER\0Browser\0Test\#2\0TEST\\0browser

For the example with multiple strings the data string to add on command line is: "test #1\0Test\#2\0TEST\\0"

The command line with REG to add modified value to registry does not contain option /f to force an overwrite. That gives you the possibility to check new value before really writing it to registry. Insert parameter /f left to /d if there should be no prompt to overwrite existing value once you verified that the batch file works as expected by you.

For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.

  • echo /?
  • endlocal /?
  • goto /?
  • if /?
  • reg /?
  • reg add /?
  • reg query /?
  • set /?
  • setlocal /?

See also Single line with multiple commands using Windows batch file for an explanation of operator &.

Mofi
  • 46,139
  • 17
  • 80
  • 143
0

As long as none of the lines inside the multi string content are doublequoted, here's how I'd probably write it:

@Echo Off
SetLocal EnableExtensions DisableDelayedExpansion

Set "_k=HKLM\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters"
Set "_v=NullSessionPipes"
Set "_s=Browser"

Set "_d="
For /F "EOL=H Tokens=2*" %%A In ('Reg Query "%_k%" /V "%_v%"'
) Do If "%%A"=="REG_MULTI_SZ" Set "_d=%%B"
If "%_d%"=="" Exit /B
Set "_d=%_d:\0\0=%"
Set "_m="
For %%A In ("%_d:\0=","%"
) Do Echo %%A|Find /I "%_s%">Nul||Call Set "_m=%%_m%%%%A\0"
If "%_m%"=="" Exit /B
Reg Add "%_k%" /V "%_v%" /T "REG_MULTI_SZ" /D %_m:~,-2% /F>Nul

Please note that this uses Find, (line 15), to match any line containing Browser, (case insensitive), if you're wanting to match lines containing only the string Browser, (case insensitive), then you may wish to take a look at the FindStr command instead, (enter FindStr /? at the Command Prompt for usage information)

There's one major caveat: the value data for a multi string registry entry can be very long indeed, if you're sure that the string data to be written back to the registry will not exceed maximum character length then you'll be okay. If not I'm afraid I cannot think of any other simple way to perform the task. (writing the data as hex into a registry file, *.reg and import/merging it).

Compo
  • 36,585
  • 5
  • 27
  • 39
  • Thanks Compo! This is what I was looking to do exactly - it is case _insensitive_ and the variables made it nice for others to be able to swap out their keys + value + data. Thumbs up! – Kachar Jul 30 '18 at 12:35