检查变量是否在PostBuildEvent中定义

时间:2019-06-18 09:06:29

标签: visual-studio cmd msbuild

我正在使用以下PostBuildEvent

<PostBuildEvent>
  IF DEFINED $(MyEnvVar) (
   mkdir "C:\tmp\"
   copy "$(TargetPath)" "$(MyEnvVar)/Addins/Software/bin/$(PlatformName)/$(TargetFileName)"
 )
</PostBuildEvent>

如果定义了我的MyEnvVar,则此事件有效。但是,如果未定义变量,则会收到错误 MSB3073 (代码为255)。

如果变量存在,我如何定义PostBuild任务以执行一些cmd操作(创建文件夹复制文件,如上所示),否则,什么也不做?

3 个答案:

答案 0 :(得分:2)

绝对不应该真正使用构建后事件。 只需创建一个目标,然后使其在构建目标之后运行即可。 在该目标中,让它复制所需的文件。像这样:

<Target Name="CopyMyStuff" AfterTargets="Build" Condition="exists('$(MyEnvVar)')" >
   <Copy SourceFiles="$(TargetPath)" DestinationFolder="$(MyEnvVar)\Addins\Software\bin\$(PlatformName)\" SkipUnchangedFiles="true" />
</Target>

我认为如果目录不存在,此复制任务将创建该目录。不错的奖励。

答案 1 :(得分:2)

在用$(Variable)文本创建批处理文件以在编译后临时执行之前,Visual Studio用XML元素PostBuildEvent的值中的Visual Studio变量的字符串替换所有出现的PostBuildEvent并成功完成链接过程。

如果根本不存在像MyEnvVar这样的引用的Visual Studio变量,则将其引用$(Variable)替换为空字符串。这将在命令行中显示:

IF DEFINED  (

在此 IF 条件下,执行批处理文件的Windows命令处理器期望DEFINED之后的环境变量的名称,而不是左括号。这是cmd.exe在评估命令 IF 的参数时检测到的语法错误,导致退出了批处理文件的处理。

一种解决方案正在使用:

<PostBuildEvent>
  set "MyEnvVar=$(MyEnvVar)"
  if defined MyEnvVar (
   mkdir "C:\tmp\"
   copy "$(TargetPath)" "$(MyEnvVar)\Addins\Software\bin\$(PlatformName)\$(TargetFileName)"
 )
</PostBuildEvent>

第一行将Visual Studio变量MyEnvVar的当前字符串值分配给环境变量MyEnvVar。因此,环境变量MyEnvVar是因为set "MyEnvVar=string value"而用字符串定义的,或者在Visual Studio变量MyEnvVar不存在或为空的情况下,在第一行之后肯定没有定义(不再)字符串,导致执行set "MyEnvVar="

命令 IF 始终具有有效的语法,因为现在始终在此命令行上指定要检查定义的环境变量的名称,而与Visual Studio变量{{1 }}。

其他说明:Windows上的目录分隔符是MyEnvVar,而不是目标路径中使用的\。 Windows文件系统访问内核功能会自动将标准合格文件名中的所有/替换为/,作为自动文件路径更正的一部分。但是最好使用100%正确的语法编写构建后事件代码,而不依赖于文件路径上的自动错误更正。

答案 2 :(得分:1)

我复制了您的脚本并遇到了相同的问题。根据错误消息The syntax of the command is incorrect,语法有问题,可能是空格,换行符,我不确定:(

  

如何定义PostBuild任务来执行一些cmd操作,(创建   文件夹复制文件(如上所示),如果变量存在,或执行   如果没有,什么都没有?

一种解决方法::也许您可以从PostBuildEvent内部删除Judgment语句。然后使用msbuild condition来判断变量是否已定义,请尝试使用如下脚本:

  <!--<PropertyGroup>
    <MyEnvVar>C:\Test</MyEnvVar>
  </PropertyGroup>-->
  <PropertyGroup>
    <PostBuildEvent Condition="$(MyEnvVar)!=''">
      IF NOT EXIST "C:\tmp\" mkdir "C:\tmp\"
      IF NOT EXIST "$(MyEnvVar)\Addins\Software\bin\$(PlatformName)\" mkdir "$(MyEnvVar)\Addins\Software\bin\$(PlatformName)\"
      copy "$(TargetPath)" "$(MyEnvVar)\Addins\Software\bin\$(PlatformName)\"
    </PostBuildEvent>
  </PropertyGroup>

在vs中,右键单击项目并将脚本添加到其中,位置应为:

<Project...>
    ...
  <!--<PropertyGroup>
    <MyEnvVar>C:\Test</MyEnvVar>
  </PropertyGroup>-->

  <PropertyGroup>
    <PostBuildEvent Condition="$(MyEnvVar)!=''">
      IF NOT EXIST "C:\tmp\" mkdir "C:\tmp\"
      IF NOT EXIST "$(MyEnvVar)\Addins\Software\bin\$(PlatformName)\" mkdir "$(MyEnvVar)\Addins\Software\bin\$(PlatformName)\"
      copy "$(TargetPath)" "$(MyEnvVar)\Addins\Software\bin\$(PlatformName)\"
    </PostBuildEvent>
  </PropertyGroup>
</Project>

然后right-click the project并选择reload project并检查它是否有助于实现您的原始目标。

1。PostBuildEvent仅在定义MyEnvVar并具有其值时才起作用。

2。当C:\tmp\$(MyEnvVar)\Addins\Software\bin\$(PlatformName)\目录不存在时,将调用两个mkdir命令

3。然后,复制命令会将项目的输出复制到目标文件夹,我删除了$(TargetFileName),因为它代表xxx.exe或xxx.dll,我认为这不是必需的,或者也许是您真正想要的是$(AssemblyName)。请让我知道它是否有助于解决您的问题:)