2014-08-29 119 views
4

當我生成C#項目(csproj文件)並編譯它時,msbuild以某種方式無法識別前和後生成事件中的變量$(ConfigurationName)$(ProjectDir)(和其他)。將Postbuild事件添加到項目中

當我手動將生成的.csproj文件中的前置和後置事件配置向下移動時,則msbuild會正確識別這些變量。

在項目中添加buildevent是我在保存項目之前做的最後一件事。

這是我如何添加:

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文件(用記事本或其他文本編輯器),剪切前和後生成事件,並將其粘貼到<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />元素下,然後msbuild將生成的.csproj文件正常生成。

將生成事件添加到.csproj文件的最佳方法是什麼,以便在生成的XML中的Import元素之後結束?

很顯然,我目前使用從Microsoft.Build.Evaluation.Project的的Xml財產AddPropertyGroup請求它的方式是不是。

示例項目:

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(); 
    } 
} 

步驟來重現

  • 創建一個新項目
  • 手動添加這應該是應用不同app.config.debug文件。調試文件
  • 添加postbuildevent:copy "$(ProjectDir)app.config.$(ConfigurationName)" "$(TargetDir)\$(ProjectName).exe.config
  • 看到項目的建立和正確的配置文件被應用
  • 使用記事本(這樣不會留下任何痕跡)
  • 運行示例項目
  • 刷新和刪除建設前和postbuild事件您創建的項目。
  • 輸出窗口會說,如果加入他們The system cannot find the file specified.
+0

似乎文件'app.config.'不存在(它缺少'ConfigurationName')。什麼是您的手動構建事件? – 2014-08-29 12:09:21

+0

不分析$(ConfigurationName)。如果我將項目文件中的buildevents移動到其中, – Alfons 2014-08-29 12:12:10

+0

猜測其中一個Imports負責設置變量,我搞砸了一個項目文件。在此之後,我必須擁有後期構建事件:或變量爲空。你可以添加構建事件的方式讓他們在底部? – Adam47 2014-08-29 12:46:08

回答

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

謝謝!完美的作品。 – Alfons 2014-09-04 14:05:19

2

項目相關的宏不被解析項目實際建造之前(構建項目包括添加引用)。除了使用$(ProjectName)的,路徑可以使用解變量(已經存在)這樣構成:

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

注意,項目名是項目硬編碼的實際名稱,但因爲你生成一個項目這應該很容易添加。

+0

這可能是一個有用的解決方法。 – Alfons 2014-09-01 12:54:04