我必须维护一个约有3500
行GOTO
乱码的批处理脚本。似乎原来的“开发人员”没有听说过 this famous paper 和模块化编程。
该脚本使用不同的选项处理多个程序的(静默)安装/卸载/重新安装。它可以拆分成几个文件,分别处理每个程序。问题是如果你试图参与另一个文件,那部分仍然会GOTO
另一个需要在原始脚本中的部分。
通常你不会在没有自动化测试的情况下进行重构(所以你可以确定你没有破坏任何东西),但我不知道该怎么做。没有测试框架。
我想出了一个部分的“解决方案”,它是characterization tests(来自Working Effectively with Legacy Code by Michael Feathers)和approval tests的某种改编:
- 创建另一个脚本:test.py
用echo替换所有命令(如copy或msiexec)
- 将输出重定向到文本文件(good.txt
),
- 更改原始批处理脚本,
- 再次运行test.py
脚本并将输出保存到另一个文本文件(current.txt
),
- diff good.txt
和current.txt
- >如果没有差异,那么我没有破坏任何东西,但如果它们不同,我需要检查我是否破坏了什么。
如何捕获并替换所有命令?我可以列出要替换的命令列表,但是还有很多字符串连接来获取要安装的程序的名称和路径。
有什么方法可以挂钩到命令行解释器(CMD.exe
)所以我可以动态替换所有对echo
安装程序的调用吗?
我是否以错误的方式处理问题?我能以某种方式做得更好吗?你有什么建议我可以使用吗?
答案 0 :(得分:2)
您可以将所有COPY
,DEL
或CALL
替换为%COPY%
,%DEL%
,...
因此,您可以将相同的文件用于生产以及测试。
@echo off
if not defined UNITTEST (
set "COPY=COPY"
set "DEL=DEL"
set "CALL=CALL"
)
%COPY% src dest
%DEL% somefile.txt
%CALL% installer.exe
从您的unittest.bat,您可以通过
启动它@echo off
set "COPY=>>trace.log ECHO COPY"
set "DEL=>>trace.log ECHO DEL"
set "CALL=>>trace.log CALL ECHO "
del trace.log
set "unittest=Active"
call production.bat
fc good.txt trace.log
答案 1 :(得分:2)
我不是Batch的专家,但我已经公平地分享了它。话虽如此,我可以提供一些提示。
忘记尝试一次完成所有操作。批处理很难调试。回显日志文件有很大帮助,但如果出现问题,它将无法捕获您需要的所有内容。
将exe和msiexec调用分解为自包含脚本。测试小脚本以获得所需的功能要容易得多。一旦你有了这个工作,从“主”脚本调用该脚本很简单。
建立一个好的协议,用于将args传递给,并从较小的脚本返回代码。如果需要为所有脚本使用通用设置,请考虑使用中央设置文件。
GOTO不是魔鬼,除非他们在整个地方传递控制权。通常,我知道使用GOTO的原因有两个。
有时候调用标签可能是更好的选择。
根据需要多长时间的遗留支持,请考虑尽可能使用Powershell。 Powershell的强大功能和调试功能远远超出了Batch简单脚本的好处。其中3500线简单已经丢失。你已经在看Python,所以也许可以用它代替。
如果您需要断点,请使用暂停。 ECHO在暂停之前需要检查的所有设置。这与我发现批次的断点接近。
回显您打算运行到日志文件的命令并实际运行它。
编写小型验证脚本,以便单独使用或使用“Master”脚本确认您获得了预期的结果。
使用正确的工具完成工作。我喜欢使用EditPadPro,RegexBuddy和BeyondCompare进行批量编辑和比较差异。有免费的工具,也可以使用NotePad ++和Windiff。在这个大小的文件中进行许多编辑最好由一个好的编辑器处理。 IE在调用cmd.exe的行的开头插入一个echo。
记住它是脚本而不是编程。虽然两者有很多重叠,但两者之间的问题可能并不一致。
总是在整理脚本之前制作脚本的备份副本。当有一个你找不到的小虫子时,非常感谢后备位置。
如果没有破坏......如果一切正常,你就不会继续工作。
始终测试更改。当你完成测试后。在那之后让别人测试它。
只是我的.02。我相信其他人可以提出更高级的建议。我对Batch的了解已从学校的硬敲击中获得,并由ss64.com补充