2014-08-29 3 views
4

Quand je produis un projet C# (csproj de fichier), puis le compiler, msbuild une certaine manière ne reconnaît pas les variables $(ConfigurationName) et $(ProjectDir) (et d'autres) en cas avant et Postbuild. Lorsque I déplace manuellement la configuration des événements pré- et post-construction dans le fichier .csproj généré, alors msbuild reconnaît ces variables correctement. Ajouter le buildevent au projet est la dernière chose que je fais avant d'enregistrer le projet.Ajout d'un événement Postbuild à un projet

Voici comment je l'ajoute:

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

L'erreur que je reçois lors de l'exécution du projet généré par msbuild est ceci:

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

Quand je puis modifier manuellement le fichier .csproj (avec bloc-notes ou un autre éditeur de texte), coupez l'événement pré-et post-construction et collez-le sous l'élément <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />, puis msbuild génère le fichier généré .csproj.

Quelle est la meilleure façon d'ajouter les événements de construction au fichier .csproj afin qu'il se termine après l'élément Import dans le résultat XML?

Apparemment, ma façon actuelle d'utiliser en lui demandant de AddPropertyGroup de la propriété Xml du Microsoft.Build.Evaluation.Project n'est pas.

Exemple de projet:

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

Étapes pour reproduire

  • Créer un nouveau projet
  • Ajoutez manuellement le fichier app.config.debug qui devrait être différent de l'application. fichier de débogage
  • Ajouter le postbuildevent: copy "$(ProjectDir)app.config.$(ConfigurationName)" "$(TargetDir)\$(ProjectName).exe.config
  • Voir que la construction du projet et le fichier de configuration correct est appliqué
  • Retirez les événements avant et Postbuild en utilisant le bloc-notes (afin de ne pas laisser de traces)
  • Exécutez l'exemple de projet
  • Recharger et construire projet que vous avez créé.
  • fenêtre de sortie va dire maintenant The system cannot find the file specified.
  • si elles sont ajoutées
+0

Il semble que le fichier 'app.config.' n'existe pas (il manque le' ConfigurationName'). Quel est votre événement de build manuel? –

+0

non $ (ConfigurationName) n'est pas analysé. Si je déplace les buildevents dans le projet, ils le sont. – Alfons

+0

Devinant que l'un des Importations est responsable de la configuration des variables, j'ai joué avec un de mes fichiers de projet. Je devais avoir les événements de post-construction après ceci: ou les variables étaient vides. Pouvez-vous ajouter les événements de construction de manière à les obtenir en bas? – Adam47

Répondre

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

Merci! fonctionne parfaitement. – Alfons

2

macros liées au projet ne sont pas analysés avant que le projet est effectivement construit (la construction d'un projet comprend l'ajout de références).Au lieu d'utiliser $(ProjectName), le chemin peut être construit en utilisant des variables de solution (qui existent déjà) comme ceci:

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

Notez que ProjectName est le nom réel du projet hardcoded, mais puisque vous générez un projet de cette devrait être facile à ajouter.

+0

Cela pourrait être une solution de contournement utile. – Alfons

Questions connexes