我修改了一个.csproj项目,将任务附加到BuildDependsOn。这将执行文件复制。如果文件复制失败,则构建失败。 (见下面的XML)。
但是,如果我在构建尝试失败后再次“构建”(在Visual Studio中),Visual Studio会报告项目已成功构建。它认为该项目为up to date
。
========== Build: 0 succeeded, 0 failed, 1 up-to-date, 0 skipped ==========
如何确保此CopyFiles目标在每个构建上运行,以防止在构建中的关键阶段失败时VS报告成功构建的问题?
<ItemGroup>
<MySourceFiles Include="$(TargetDir)*.dll;$(TargetDir)*.pdb"/>
</ItemGroup>
<Target Name="CopyFiles">
<Copy SourceFiles="@(MySourceFiles)" DestinationFolder="$(DestFolder)\subfolder" />
<Copy SourceFiles="$(ProjectDir)AnotherFile.txt" DestinationFolder="$(DestFolder)" />
<OnError ExecuteTargets="CopyFiles_Failed" />
</Target>
<Target Name="CopyFiles_Failed">
<Error text="File copies failed">
</Error>
</Target>
<PropertyGroup>
<BuildDependsOn>
$(BuildDependsOn);
CopyFiles
</BuildDependsOn>
</PropertyGroup>
答案 0 :(得分:1)
正如@maxkenir所提到的那样,Inputs and Output parameter in a target define the set of files the build should check to decide whether it is up to date。
输入
形成此目标输入的文件。多个文件由分号分隔。将文件的时间戳与输出中文件的时间戳进行比较,以确定目标是否是最新的。有关更多信息,请参阅增量构建,如何:增量构建和MSBuild转换。
输出
形成输出到此目标的文件。多个文件由分号分隔。将文件的时间戳与输入中文件的时间戳进行比较,以确定目标是否是最新的。有关更多信息,请参阅增量构建,如何:增量构建和MSBuild转换。
article on Incremental Builds进一步解释了使用它们的过程。
对于简单的复制文件操作,基本上它看起来像是:
<Target Name="Backup" Inputs="@(files)"
Outputs="@(Compile->'$(BackupFolder)%(Identity).bak')">
<Copy SourceFiles="@(Compile)" DestinationFiles=
"@(Compile->'$(BackupFolder)%(Identity).bak')" />
</Target>
有关这些MsBuild transforms can be found again on MSDN的更多信息,在您的情况下可能非常接近:
<Target Name="CopyOutputs"
Inputs="@(BuiltAssemblies)"
Outputs="@(BuiltAssemblies -> '$(OutputPath)%(Filename)%(Extension)')">
<Copy
SourceFiles="@(BuiltAssemblies)"
DestinationFolder="$(OutputPath)"/>
</Target>
但输入和输出也会accept an Item Group,您也可以进行多次转换。
答案 1 :(得分:1)
对于记录,这是我的特定解决方案XML(使用@jessehouwing的答案):
首先:创建一个包含我要复制的所有文件的MySourceFiles
项目组,即使我需要将文件复制到不同的文件夹中。
其次:使用保存其目标文件夹的元数据值标记要复制的每个文件项:DestFolder
。
然后我可以使用变换生成输出路径列表:
@(MySourceFiles->'%(DestFolder)%(Filename)%(Extension)')
要指定目标的输入和输出,我可以使用MySourceFiles和变换。
<PropertyGroup>
<DEST>c:\where\to\copy\files\</DEST>
</PropertyGroup>
<ItemGroup>
<!-- dlls/pdbs go in DEST\bin -->
<MySourceFiles Include="$(TargetDir)*.pdb;$(TargetDir)*.dll">
<DestFolder>$(DEST)bin\</DestFolder>
</MySourceFiles>
<!-- anotherfile.txt goes in DEST -->
<MySourceFiles Include="$(ProjectDir)anotherfile.txt">
<DestFolder>$(DEST)</DestFolder>
</MySourceFiles>
</ItemGroup>
<Target
Name="CopyFiles"
Inputs="@(MySourceFiles)"
Outputs="@(MySourceFiles->%(DestFolder)%(Filename)%(Extension))">
<Copy SourceFiles="@(MySourceFiles)" DestinationFiles="@(MySourceFiles->'%(DestFolder)%(Filename)%(Extension)')" />
</Target>
<!-- inject target into build process -->
<PropertyGroup>
<BuildDependsOn>
$(BuildDependsOn);
CopyFilesToSDK
</BuildDependsOn>
</PropertyGroup>