基本上
这里的第一次海报......我不仅在搜索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
答案 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"