将Postbuild事件添加到项目中

时间:2014-08-29 12:04:44

标签: c# msbuild msbuild-propertygroup microsoft.build

当我生成一个C#项目(csproj文件)然后编译它时,msbuild以某种方式无法识别变量$(ConfigurationName)$(ProjectDir)(以及其他)前期和后期活动。

当我手动将生成的.csproj文件中的pre-andbuild事件配置进一步向下移动时,msbuild会正确识别这些变量。

在保存项目之前,我最后要做的就是将构建添加到项目中。

这是我添加它的方式:

using Microsoft.Build.Construction;
using Microsoft.Build.Evaluation;

private const string PreBuildEventFixture = "PreBuildEvent";
private const string PostBuildEventFixture = "PostBuildEvent";
private const string PreBuildEvent = "attrib -R \"$(ProjectDir)app.config\"";
private const string PostBuildEvent = "copy \"$(ProjectDir)app.config.$(ConfigurationName)\" \"$(TargetDir)\\$(ProjectName).dll.config\" \r\n attrib -R \"$(ProjectPath)\"";

public void AddBuildEvents(Project project)
{
    ProjectPropertyGroupElement propertyGroupElement = project.Xml.AddPropertyGroup();
    propertyGroupElement.AddProperty(PreBuildEventFixture, PreBuildEvent);
    propertyGroupElement.AddProperty(PostBuildEventFixture, PostBuildEvent);
}

通过msbuild运行生成的项目时出现的错误是:

The command "copy "app.config." "\.dll.config"" exited with code 1

当我手动编辑.csproj文件(使用记事本或其他文本编辑器)时,剪切pre-post和postbuild事件,并将其粘贴到<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />元素下面,然后msbuild构建生成的{ {1}}文件正常。

将构建事件添加到.csproj文件的最佳方法是什么,以便它在结果.csproj中的Import元素之后结束?

显然,我目前使用XMLAddPropertyGroupXml属性的Microsoft.Build.Evaluation.Project请求它的方式不是。

示例项目:

[ProjectPropertyGroupElement][1]

重现的步骤

  • 创建新项目
  • 手动添加app.config.debug文件,该文件应与app.debug文件不同
  • 添加postbuildevent:using System.IO; using Microsoft.Build.Construction; using Microsoft.Build.Evaluation; class Program { private const string PreBuildEventFixture = "PreBuildEvent"; private const string PostBuildEventFixture = "PostBuildEvent"; private const string PreBuildEvent = "attrib -R \"$(ProjectDir)app.config\""; private const string PostBuildEvent = "copy \"$(ProjectDir)app.config.$(ConfigurationName)\" \"$(TargetDir)\\$(ProjectName).exe.config\" \r\n attrib -R \"$(ProjectPath)\""; private const string ProjectFile = @"C:\test\TestProject\TestProject.csproj"; static void Main(string[] args) { if (!File.Exists(ProjectFile)) throw new FileNotFoundException("ProjectFile not found"); ProjectCollection collection = new ProjectCollection(); Project project = collection.LoadProject(ProjectFile); ProjectPropertyGroupElement propertyGroupElement = project.Xml.AddPropertyGroup(); propertyGroupElement.AddProperty(PreBuildEventFixture, PreBuildEvent); propertyGroupElement.AddProperty(PostBuildEventFixture, PostBuildEvent); project.Save(); collection.UnloadAllProjects(); } }
  • 看到项目构建和正确的配置文件已应用
  • 使用记事本删除预建和事后事件(以免遗留任何痕迹)
  • 运行示例项目
  • 重新加载并构建您创建的项目。
  • 输出窗口现在会显示copy "$(ProjectDir)app.config.$(ConfigurationName)" "$(TargetDir)\$(ProjectName).exe.config

2 个答案:

答案 0 :(得分:4)

var propertyGroupElement = project.Xml.CreatePropertyGroupElement();
project.Xml.AppendChild(propertyGroupElement);
propertyGroupElement.AddProperty(PreBuildEventFixture, PreBuildEvent);
propertyGroupElement.AddProperty(PostBuildEventFixture, PostBuildEvent);

答案 1 :(得分:2)

如果在实际构建项目之前添加项目相关宏(构建项目包括添加引用),则不会解析项目相关宏。可以使用解决方案变量(已经存在)构建路径,而不是使用$(ProjectName),如下所示:

copy "$(SolutionDir)ProjectName\app.config.$(Configuration)" "$(SolutionDir)ProjectName\bin\$(Configuration)\ProjectName.dll.config"

请注意,ProjectName是硬编码项目的实际名称,但由于您要生成项目,因此应该很容易添加。