我有一个奇怪的解决方案,我需要其中一个项目来“编译”另一个文件。
编译器(这里显示一个最小的例子)如下(MSBuild自定义任务):
public class MyCompileTask : Task
{
[Required]
public ITaskItem[] InputFiles { get; set; }
[Output]
public ITaskItem[] OutputFiles { get; set; }
public override bool Execute()
{
var generatedFileNames = new List<string>();
foreach (var inputFile in this.InputFiles)
{
var inputFileName = inputFile.ItemSpec;
var outputFileName = Path.ChangeExtension(inputFileName, ".res.txt");
var source = File.ReadAllText(inputFileName);
var compiled = source.ToUpper();
File.WriteAllText(outputFileName, compiled + "\n\n" + DateTime.Now);
generatedFileNames.Add(outputFileName);
}
this.OutputFiles = generatedFileNames.Select(name => new TaskItem(name)).ToArray();
return true;
}
}
如您所见,它只会改变输入文件的内容。
这是项目A - “编译器”库。
项目B,现在是主应用程序,有一个文件“lorem.txt”需要“编译”成“lorem.res.txt”并作为EmbeddedResource放在B.exe / B.dll中。 / p>
在B.csproj中我添加了以下内容:
<PropertyGroup>
<CoreCompileDependsOn>$(CoreCompileDependsOn);InvokeMyCompile</CoreCompileDependsOn>
</PropertyGroup>
<UsingTask TaskName="MyCompiler.MyCompileTask" AssemblyFile="$(MSBuildProjectDirectory)\..\MyCompiler\bin\$(Configuration)\MyCompiler.dll" />
<Target Name="MyCompile" Inputs="lorem.txt" Outputs="lorem.res.txt">
<MyCompileTask InputFiles="lorem.txt">
<Output TaskParameter="OutputFiles" PropertyName="OutputFiles" />
</MyCompileTask>
</Target>
<Target Name="InvokeMyCompile" Inputs="lorem.txt" Outputs="lorem.res.txt">
<Exec Command=""$(MSBuildBinPath)\MSBuild.exe" /t:MyCompile "$(ProjectDir)$(ProjectFileName)"" />
</Target>
(2层目标和一个明确的msbuild.exe调用是一种解决方法to another problem。实际上,这个例子的大部分都是从那个Q中偷来的。)
最重要的部分是有效的,即当我更改lorem.txt和build时,lorem.res.txt会重新生成。
然而
如何在csproj文件中声明这些依赖项?
Bonus问题:如何将输出文件(lorem.res.txt)标记为生成的EmbeddedResource,这样我就不必在VS中跟踪它,但它仍然被放入程序集中?
答案 0 :(得分:0)
•当物理删除lorem.res.txt时,构建什么也不做(说它是最新的),直到我真正刷新VS中的项目。因此,MSBuild并不“知道”构建项目实际上需要lorem.res.txt。
我创建了一个演示并在我身边重现了你的问题,你可以使用msbuild命令行来避免它。
•更重要的是,当我更改项目A中的任何内容时,项目B会重新编译,但不会重新运行编译lorem.txt - &gt; lorem.res.txt。所以MSBuild并不“知道”转换依赖于另一个项目。
因为自定义任务引用了DLL文件,所以在更改项目A中的任何内容时,需要重建项目以生成更新的DLL文件。
Bonus问题:如何将输出文件(lorem.res.txt)标记为生成的EmbeddedResource,这样我就不必在VS中跟踪它,但它仍然被放入程序集中?
您可以在BeforeBuild目标中添加自定义ItemGroup来实现它。
<Target Name="BeforeBuild" DependsOnTargets="MyCompile">
<ItemGroup>
<Content Include="lorem.res.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Target>