通过批处理文件/命令行仅从注册表值REG_MULTI_SZ中删除特定数据

时间:2018-07-26 20:16:05

标签: batch-file registry batch-processing

全部;

我整天都在互联网上,试图编写/工作一个批处理文件。

只是开始-我希望仅通过批处理文件和/或命令行来使这项工作生效。

我要删除特定数据(不区分大小写,因为数据可能是'data''Data''DATA')。

我所见过的大多数操作系统都是Win XP计算机。具体如下:

我希望从browser注册表值中专门删除数据“ Browser”(同样也可以是“ BROWSER”或“ REG_MULTI_SZ) ,可以在以下位置找到子项:

HKLM\SYSTEM\CurrentControlSet\Services\lanmanserver\parameters

实际值为:

NullSessionPipes

我总是看到此值内有多条数据(“ browser”位于混合位置)。无论browser是值中的唯一数据还是多个数据,我都必须能够执行.bat才能删除它。

我的研究指向我查询数据,删除“ browser”数据,然后重新插入其余数据-我只是无法成功完成此操作。

我试图在以下位置在计算机(Win10)上创建一个虚拟的测试键/值:

HKCU\Temp\Test

其中包含以下数据:

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

我所做的一切,都无法从此数据中仅删除// browser的任何形式,而其余的“ Test #x”数据都将保留。

请提供任何人都能提出的解决方案的建议。

更新 这是我在整个研究过程中能够整理的代码(我整理了几个不同的批处理文件,但没有取得积极的成果): (注意:我绝不会为任何此代码功劳,因为大部分代码都是在许多不同的位置进行编译的):

Test1.bat

此测试不断删除整个值,我无法弄清。

    @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

这是尝试将数据导出到txt文件,然后删除“浏览器”的尝试-另一尝试失败。

    @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

此尝试最终将所有数据替换为“ Test”值的“%b”

    @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

我确实遇到了一些主题,用户曾说过,如果将数据转换为HEX /二进制文件,这样做会更容易吗? 我希望这有助于使某人了解我在这里到底在做什么错。

2 个答案:

答案 0 :(得分:0)

这是此任务的批处理批处理文件:

@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

命令行的输出

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

FOR 在后台以cmd /C开始的单独命令过程中执行,取决于 REG 的版本。

在Windows Vista和Windows Server 2008以及所有更高版本的Windows上,输出以空行开头,第二行是注册表项,第三行包含注册表值名称,值类型和由空格分隔的值数据。

>

在Windows XP和Windows Server 2003上,输出以空行开头,下一版本为 REG ,再有一个空行,第四行包含注册表项,第五行最后包含注册表值名称,值类型和带有四个缩进空格并由水平制表符分隔的值数据。

因此,从 REG 的不同输出中,只能跳过前两行。下一行包含Windows Vista / Server 2008和所有更高版本的Windows上的关注数据。但是在Windows XP和Server 2003上,有必要从捕获的 REG 输出中处理更多行,直到达到感兴趣数据的第五行为止。因此,使用另外两个 IF 条件可以100%确保在退出Windows之前,将注册表值NullSessionPipes的多字符串值确实分配给了环境变量NullSessionPipes。循环并处理值。

在具有NullSessionPipes但不包含任何字符串的Windows XP上

REG 的输出:

 
! REG.EXE VERSION 3.0
 
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\lanmanserver\parameters
····NullSessionPipes»   REG_MULTI_SZ»   \0
上面输出示例中的

·和下面所有其他示例表示缩进/分隔空格字符。 »代表水平制表符。

在具有NullSessionPipes但不包含任何字符串的Windows XP上

REG 的输出:

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

在Windows XP上的 REG 的示例输出,其中NullSessionPipes包含字符串:

 
! 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

在Windows 7上的 REG 的示例输出,其中NullSessionPipes包含字符串:

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

对于具有多个字符串的示例,要在命令行上添加的数据字符串为:"test #1\0Test\#2\0TEST\\0"

带有 REG 用来向注册表添加修改后的值的命令行不包含用于强制覆盖的选项/f。这使您可以在将新值真正写入注册表之前检查它。如果在确认批处理文件能够按预期工作后没有提示覆盖现有值的提示,请在/f左边插入参数/d

要了解所使用的命令及其工作方式,请打开命令提示符窗口,在其中执行以下命令,并非常仔细地阅读每个命令显示的所有帮助页面。

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

有关运算符&的说明,另请参见Single line with multiple commands using Windows batch file

答案 1 :(得分:0)

只要多字符串内容中的所有行都没有被双引号,这就是我可能会写的方式:

@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

请注意,它使用Find(第15行),以匹配任何包含Browser(不区分大小写)的行,如果您想匹配仅包含字符串Browser的行,(不区分大小写),那么您不妨查看一下FindStr命令,(在命令提示符下输入FindStr /?以获得使用信息)

有一个主要警告:多字符串注册表项的值数据确实可能很长,如果您确定要写回注册表的字符串数据不会超过最大值字符长度,那么您就可以了。如果没有,我恐怕无法想到其他任何简单的方法来执行任务。 (将十六进制数据写入注册表文件*.reg并导入/合并)

相关问题