具有多个if/copy组合的post-build事件仅在第一个文件不存在时执行

Jer*_*ers 6 delphi post-build-event

鉴于bin\内部德尔福项目中包含的文件目录Cert.pemKey.pem低于德尔福后生成事件的唯一副本,如果这两个文件C:\Binaries\Cert.pem不存在:

if not exist $(OUTPUTDIR)Cert.pem (copy bin\Cert.pem $(OUTPUTDIR))
if not exist $(OUTPUTDIR)Key.pem (copy bin\Key.pem $(OUTPUTDIR))
Run Code Online (Sandbox Code Playgroud)

一旦C:\Binaries\Cert.pem存在,Key.pem永远不会复制该文件.

如何在后期制作活动中解决这个问题?

编辑:与我的2014年帖子不同,这确实可以使用括号.请参阅下面的答案.

Jer*_*ers 10

Delphi后构建事件的问题在于它们不是批处理文件.

这意味着看起来像行的语句被Delphi IDE连接成一个大的&&符号分隔语句.这确保命令按顺序执行,根据命令重定向,管道 - Windows CMD - SS64.com:

commandA &  commandB      Run commandA and then run commandB
Run Code Online (Sandbox Code Playgroud)

所以这是执行的实际语句:

if not exist $(OUTPUTDIR)Cert.pem (copy bin\Cert.pem $(OUTPUTDIR))&if not exist $(OUTPUTDIR)Key.pem (copy bin\Key.pem $(OUTPUTDIR))
Run Code Online (Sandbox Code Playgroud)

这里的问题是,现在第二个if被视为第一个if语句的"then"部分的延续:第二个语句if$(OUTPUTDIR)Cert.pem存在时永远不会执行.

有用的是一个鲜为人知的功能,您可以将每个命令包装在括号内.通常这是为了允许一个命令跨越多行(特别是for iffor.. do循环),但它也适用于一行.

包含if括号内的语句的每一行确保它们成为不影响其他行的独立语句,即使它们与&符号分隔符连接在一起.

在对话框中,它看起来像这样:

(if not exist $(OUTPUTDIR)Cert.pem (copy bin\Cert.pem $(OUTPUTDIR)))
(if not exist $(OUTPUTDIR)Key.pem (copy bin\Key.pem $(OUTPUTDIR)))
Run Code Online (Sandbox Code Playgroud)

这样,IDE将其转换为一个语句:

(if not exist $(OUTPUTDIR)Cert.pem (copy bin\Cert.pem $(OUTPUTDIR)))&(if not exist $(OUTPUTDIR)Key.pem (copy bin\Key.pem $(OUTPUTDIR)))
Run Code Online (Sandbox Code Playgroud)

现在它按预期工作:

  • $(OUTPUTDIR)Cert.pem存在,但$(OUTPUTDIR)Key.pem没有,只是$(OUTPUTDIR)Cert.pem被复制
  • 什么$(OUTPUTDIR)Cert.pem时候存在但确实存在$(OUTPUTDIR)Key.pem,只$(OUTPUTDIR)Key.pem复制
  • 当两者都不存在时,两者都被复制
  • 当两者都存在时,都不会被复制

在编写我的2014年后Delphi预建/预链接/ postbuild事件时,我不知道这个"技巧" ,所以我需要为它编写更新.

搜索批处理文件括号网站:microsoft.com -site:social.technet.microsoft.com -site:answers.microsoft.com没有在官方文档中显示它,但我并不感到惊讶,因为它变得歇斯底里,而不是设计的.或者像Old New Thing属性h2g2:

就像宇宙一样,如果有人完全理解批处理,那么语言将立即被无限怪异和更复杂的自身版本所取代.这显然至少发生过一次;)

我能找到的最好的文档是在括号/括号 - Windows CMD - SS64.com:

括号可用于跨多行分割命令.这可以使代码更具可读性.将为代码块评估变量,就像命令是单行一样.

 (command)

 (
  command
  command )
Run Code Online (Sandbox Code Playgroud)

在括号内打破的事情CMD shell在评估括号时不会使用任何强大的智能,因此例如下面的命令将失败:

IF EXIST MyFile.txt (ECHO Some(more)Potatoes)
Run Code Online (Sandbox Code Playgroud)

...


Bri*_*ian 5

使用多个构建事件而不是将两个命令放在同一个事件中。


执行构建事件的源代码行。

我可以很容易地缩短这一点:构建事件不是批处理文件。

发生的情况是构建事件中的所有行都使用与号 (&) 符号连接在一起,这些符号用于在一个命令行上执行多个命令。

这意味着所有花哨的控制结构(if 语句、setlocal、for 循环)在构建事件中都是不可能的。


参考:粘贴自博客文章:Jeroen W. Pluimers 编写的Delphi prebuild/prelink/postbuild events

让我想知道你为什么问,因为看起来你在 2014 年写了答案。:)

  • @Victoria 好主意!我在提问时已经准备好了大部分答案,但被打断了,所以决定还是发帖看看其他人是否有不同的解决方案,然后决定让答案更具可读性。让我知道如何进一步改进它。 (2认同)