如何重构充斥着GOTO的Windows批处理脚本?

时间:2014-03-05 20:10:34

标签: batch-file refactoring automated-tests

我必须维护一个约有3500GOTO乱码的批处理脚本。似乎原来的“开发人员”没有听说过 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.txtcurrent.txt - >如果没有差异,那么我没有破坏任何东西,但如果它们不同,我需要检查我是否破坏了什么。

部分解决方案的问题

如何捕获并替换所有命令?我可以列出要替换的命令列表,但是还有很多字符串连接来获取要安装的程序的名称和路径。

CMD级别捕获/挂钩?

有什么方法可以挂钩到命令行解释器(CMD.exe)所以我可以动态替换所有对echo安装程序的调用吗?

其他建议?

我是否以错误的方式处理问题?我能以某种方式做得更好吗?你有什么建议我可以使用吗?

2 个答案:

答案 0 :(得分:2)

您可以将所有COPYDELCALL替换为%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的原因有两个。

    1. 跳过不需要运行的代码块。
    2. 将值设置为变量。请注意,有一个错误可以阻止变量在“IF”语句块中设置其值。这个小虫子曾经让我头疼不已。
    3. 有时候调用标签可能是更好的选择。

    4. 根据需要多长时间的遗留支持,请考虑尽可能使用Powershell。 Powershell的强大功能和调试功能远远超出了Batch简单脚本的好处。其中3500线简单已经丢失。你已经在看Python,所以也许可以用它代替。

    5. 如果您需要断点,请使用暂停。 ECHO在暂停之前需要检查的所有设置。这与我发现批次的断点接近。

    6. 回显您打算运行到日志文件的命令并实际运行它。

    7. 编写小型验证脚本,以便单独使用或使用“Master”脚本确认您获得了预期的结果。

    8. 使用正确的工具完成工作。我喜欢使用EditPadPro,RegexBuddy和BeyondCompare进行批量编辑和比较差异。有免费的工具,也可以使用NotePad ++和Windiff。在这个大小的文件中进行许多编辑最好由一个好的编辑器处理。 IE在调用cmd.exe的行的开头插入一个echo。

    9. 记住它是脚本而不是编程。虽然两者有很多重叠,但两者之间的问题可能并不一致。

    10. 总是在整理脚本之前制作脚本的备份副本。当有一个你找不到的小虫子时,非常感谢后备位置。

    11. 如果没有破坏......如果一切正常,你就不会继续工作。

    12. 始终测试更改。当你完成测试后。在那之后让别人测试它。

    13. 只是我的.02。我相信其他人可以提出更高级的建议。我对Batch的了解已从学校的硬敲击中获得,并由ss64.com补充