BATCH文件删除配置文件条目

时间:2012-07-20 23:21:22

标签: batch-file configuration-files

基本上

这里的第一次海报......我不仅在搜索SO,而且在整个互联网上搜索过去2天的答案。我想要一个批处理文件(.bat),它在卸载期间运行,打开一个配置(.cfg)文件,找到一个条目,然后将其删除,然后完成卸载。

到目前为止我有什么:

我有一个运行批处理文件的安装程序将条目添加到配置文件中:

[Area.01]
Title=Unique to entry
Location=Unique to entry
Active=Required but in all entries
Layer=Required with Unique Number
Required=Required but in all entries

[Area.02]
Title=Unique to entry
Location=Unique to entry
Active=Required but in all entries
Layer=Required with Unique Number
Required=Required but in all entries

我有安装批处理文件扫描配置并添加下一个条目号,条目的内容,以及保存条目索引的REGISTRY键;所以逻辑上下一个条目是[Area.03]。但是,此文件包含100多个条目。

我想要的是批处理文件读取注册表项,它执行,找到条目,它做什么,并删除整个条目,这就是我在这里的原因。以下是我到目前为止的情况:

@echo off

REG QUERY "HKLM\SOFTWARE\Name of File" /v SceneryCFGPath
IF ERRORLEVEL 1 GOTO ERROR1
FOR /F "tokens=3 skip=2" %%i IN ('REG QUERY "HKLM\SOFTWARE\Name of File" /v SceneryCFGPath') DO SET VAR1=%%i
CD "%VAR1%"

REG QUERY "HKLM\SOFTWARE\Name of File" /v SceneryIndex
IF ERRORLEVEL 1 GOTO ERROR2
FOR /F "tokens=3 skip=2" %%i IN ('REG QUERY "HKLM\SOFTWARE\Name of File" /v SceneryIndex') DO SET VAR2=%%i
TYPE scenery.cfg | FINDSTR /V Area.%VAR2%
REG DELETE "HKLM\SOFTWARE\Name of File" /F
GOTO END

:ERROR1
ECHO There was an Error while changing to Directory "%VAR1%"...
PAUSE
GOTO ERROR2

:ERROR2
ECHO There was an Error while unregistering from Scenery Library ! Please delete the Area manually...
PAUSE
GOTO END

:END
del "%~f0"

使用FINDSTR时,它会成功找到该条目,但会删除第一行:[Area.03]。我需要它做的是删除该条目和该条目的其他部分。

当我试图在FINDSTR中包含其他条目时:

TYPE scenery.cfg | FINDSTR /V /N Area.%VAR2% | Title | Active | Layer | Required

它会删除每个条目的所有行。

我真的更喜欢这是一个批处理文件,因为它可以在Windows XP,Vista和7,32和64位系统上运行。由于这些特定的Windows系统都具有 CMD。 EXE ,不需要任何额外的库或程序。

我完美无缺, EXCEPT 删除配置文件中的所有条目。我希望我没有混淆任何人,但任何帮助将不胜感激!

Sven2157

1 个答案:

答案 0 :(得分:1)

在解决您提出的问题之前,还有一些其他问题需要解决您的错误处理问题。

您测试是否存在特定的注册表项值,如果未找到,则尝试打印出不存在的键值!这不起作用; - )

您尝试将CD刻录到找到的路径值,但无法保证路径有效。您可能想要检查错误。此外,当前驱动器可能与路径驱动器不匹配,因此您应该使用CD / D(或PUSHD)。

每个注册表项值对使用2个REG QUERY操作 - 一个用于测试存在,另一个用于解析值。每个键值只需要1个REG QUERY。

批处理文件完成后将自行删除。这将导致“无法找到批处理文件”错误。也许你不在乎,但你可能应该在调用这批时将stdout重定向到nul。

由于您的批处理文件会自动删除,因此您可以简化错误处理。每个错误都不需要单独的例程。只需调用一般错误例程,传入错误消息。完成后,错误例程可以进入结束例程,这会终止批处理。因此,无需担心从错误调用返回。

我已将上述所有想法纳入我的代码中。

我还假设您实际上想要修改“scenery.cfg”文件,而不是简单地将更改后的表单回显到屏幕上。我将输出重定向到一个新文件,然后将新文件重命名为旧名称,从而销毁原始文件。

现在,为了解决您的原始问题 - 批处理没有任何本机实用程序,可以方便地提取两个标记行之间的一系列行。由于您不想依赖任何非本机实用程序,因此您必须在循环中处理每一行并确定是否应包含该行。

我看到了两种简单的方法:注意 - 没有任何代码经过测试。这些概念都很合理,但我可能已经介绍了一个易于修复的愚蠢错误

1 - 使用单个循环检查每一行,并在找到所选区域时开始排除该行,并在下一个区域开始时恢复

代码使用SET搜索和替换来测试以查看该行是否包含相关字符串。

读取文件的经典技术是FOR / F循环。但它删除了空白行。因此代码扩展为在每个[Area.nn]部分之前添加一个空行。需要延迟扩展,但如果启用了延迟扩展,则包含!的FOR变量值将被破坏。所以我在循环中打开和关闭延迟扩展。如果您知道!永远不会出现在文件中,那么您可以在顶部启用延迟扩展,并从循环中删除SET LOCAL和ENDLOCAL。

@echo off
setlocal disableDelayedExpansion
set regPath="HKLM\SOFTWARE\Name of File"

set "myPath="
for /f "tokens=3 skip=2" %%A in ('reg query %regPath% /v SceneryCFGPath') do set "myPath=%%A"
if not defined myPath call :error Unable to locate SceneryCFGPath
cd /d "%myPath%" 2>nul || call :error Unable to CD to "%myPath%"

set "area="
for /f "tokens=3 skip=2" %%A IN ('reg query %regPath% /v SceneryIndex') do set "area=%%A"
if not defined area call :error Unable to unregister from Scenery Library ! Please delete the Area manually...

>scenery.cfg.new (
  set "del="
  for /f "delims=" %%A in (scenery.cfg) do (
    set "ln=%%A"
    setlocal enableDelayedExpansion
    if "!ln:[Area.%area%=!" neq "!ln!" (
        set del=1
    ) else if "!ln:[Area.=!" neq "!ln!" (
        set "del="
        echo(
    )
    if not defined del echo !ln!
    endlocal
  )
)
move /y scenery.cfg.new scenery.cfg

reg delete %regPath% /f
goto end

:error
echo ERROR: %*
pause

:end
del "%~f0"

2 - 使用FINDSTR查找所选区域的开头,使用第二个FINDSTR查找下一个区域的开头。

/ N选项用于获取匹配行的行号。 FOR / F用于解析并将结果赋值给值。一旦找到下一个区域,GOTO就需要突破第二个循环。

最后,第三个FOR / F用于读取FINDSTR命令前面带有行号的文件。解析每一行并排除相应的行。

请注意,如果某行以:开头,则此代码无法正常工作。可以使用更多代码删除限制,但我不认为在您的情况下需要它。

@echo off
setlocal disableDelayedExpansion
set regPath="HKLM\SOFTWARE\Name of File"

set "myPath="
for /f "tokens=3 skip=2" %%A in ('reg query %regPath% /v SceneryCFGPath') do set "myPath=%%A"
if not defined myPath call :error Unable to locate SceneryCFGPath
cd /d "%myPath%" 2>nul || call :error Unable to CD to "%myPath%"

set "area="
for /f "tokens=3 skip=2" %%A IN ('reg query %regPath% /v SceneryIndex') do set "area=%%A"
if not defined area call :error Unable to unregister from Scenery Library ! Please delete the Area manually...

set "beginDel="
for /f "delims=:" %%N in ('findstr /nbc:"[Area.%area%]" scenery.cfg') do set beginDel=%%N
if not defined beginDel goto end

set "endDel="
for /f "delims=:" %%N in ('findstr /nbc:"[Area." scenery.cfg') do if %%N gtr beginDel (
  set endCond=if %%A gre %%N
  goto :break
)
:break

>scenery.cfg.new (
  for /f "tokens=1* delims=:" %%A in ('findstr /n "^" scenery.cfg') do (
    if %%A lss %beginDel% %endCond% echo(%%B
  )
)
move /y scenery.cfg.new scenery.cfg

reg delete %regPath% /f
goto end

:error
echo ERROR: %*
pause

:end
del "%~f0"