web-dev-qa-db-fra.com

Comment inclure par programmation un fichier dans mon projet?

Contexte

Je fais une application d'aide qui reformate certains fichiers de code et crée de nouveaux fichiers de code, qui doivent être ajoutés à mon autre projet, afin que je puisse utiliser le nouveau code tout de suite, mais j'ai de la difficulté à ajouter ce nouveau fichier de code dans mon projet automatiquement. Au fait, c'est en c # et l'application d'assistance est WinForms.

Tentatives ratées

Cette question La seule réponse a deux façons de le faire, mais je n'ai pu en faire fonctionner aucune. Avec le premier, je ne trouve pas de Microsoft.Build Assembly à référencer, et dans l'autre il n'y a clairement pas assez d'arguments pour une ligne de commande.

Question

Comment inclure par programmation un fichier dans un projet sans utiliser d'applications tierces?

Fondamentalement, je cherche l'équivalent de ceci:

... Mais fait en utilisant du code.

Exigences

Ce sont les fonctionnalités que je suppose que la solution devrait offrir:

  • Sélectionnez la solution qui a le projet auquel nous ajoutons le fichier
  • Sélectionnez le projet dans lequel le fichier doit être ajouté
  • Sélectionnez le répertoire dans le projet
  • Et, bien sûr, le fichier que nous ajoutons

Le progrès

Avec l'aide de l'utilisateur @ psubsee2003, j'ai pu trouver le Microsoft.Build.dll fichier dans C:\Windows\Microsoft.NET\Framework\v4.0.30319 dossier sur mon ordinateur et l'importer avec succès en modifiant le cadre cible de mon projet en version 4 Profil complet , pas le profil client par défaut.

Et j'ai trouvé comment utiliser la méthode AddItem:

var p = new Microsoft.Build.Evaluation.Project(@"C:\projects\MyProject.csproj");
p.AddItem("Compile", @"C:\folder\file.cs");
p.Save();

Le fichier apparaîtra dans le dossier racine du projet sauf si le projet avait déjà un dossier appelé folder, auquel cas le fichier y sera placé. Donc, fondamentalement, le fichier sera placé dans la chaîne de dossiers la plus profonde trouvée dans le chemin du fichier d'origine vers le dossier racine.

37
user1306322

Cela a fonctionné pour moi juste en l'ajoutant au ProjectFolder, et également ajouter le dossier par programme comme ceci.

var p = new Microsoft.Build.Evaluation.Project(@"C:\projects\BabDb\test\test.csproj");
        p.AddItem("Folder", @"C:\projects\BabDb\test\test2");
        p.AddItem("Compile", @"C:\projects\BabDb\test\test2\Class1.cs");
        p.Save();
26
Boot750

En complément de la réponse de Boot750 (d'abord suggéré comme une modification de sa réponse, mais republié en tant que version autonome)

Vous devez noter que l'appel à new Microsoft.Build.Evaluation.Project(path) provoque le chargement du projet dans un cache global géré par l'assembly Microsoft.Build.Evaluation. Appeler à nouveau new Project(path) avec le même chemin, sans le décharger d'abord de la collection globale/redémarrer votre application provoquera une exception comme:

Un projet équivalent (un projet avec les mêmes propriétés globales et la même version d'outils) est déjà présent dans la collection de projets, avec le chemin "YOUR_PATH". Pour charger un équivalent dans cette collection de projets, déchargez d'abord ce projet.

même si la variable p est hors de portée.

Vous devrez donc peut-être adopter un modèle plus semblable à celui-ci, si vous prévoyez d'utiliser le modèle Load/AddItem/Save à plusieurs reprises:

 var p =
Microsoft.Build.Evaluation
  .ProjectCollection.GlobalProjectCollection
    .LoadedProjects.FirstOrDefault(pr => pr.FullPath == projFilePath);

if (p == null)
   p = new Microsoft.Build.Evaluation.Project(projFilePath);
10
Caius Jard

La façon la plus simple de procéder consiste à modifier le fichier Project. Comme il ne s'agit que d'un fichier MSBUILD, VS récupérera la modification et vous invitera à recharger le projet. Chargez le fichier de projet au format XML et recherchez le premier <Compile Include="Name of File.cs" />. Insérez un nouveau <Compile Include="NewFile.CS" /> et vous avez terminé.

Comme autre option, vous pouvez supprimer tous les <Compile> balises et remplacez-les par <Compile Include="*.cs" />

6
rerun

Juste pour ajouter à la réponse de @ caius-jard

Une fois que le projet est dans GlobalProjectCollection, il est conservé en mémoire et ne reflète aucune modification manuelle apportée au projet. Cela inclut la mise à jour du fichier .csproj et l'utilisation de VS pour supprimer les fichiers générés.

Si vous supprimez le fichier généré et exécutez à nouveau le code, le projet sera mis à jour pour contenir 2 du fichier généré. Utilisez la fonction ReevaluateIfNecessary () pour mettre à jour l'instance du projet avant de l'utiliser comme ceci:

var p = Microsoft.Build.Evaluation
        .ProjectCollection.GlobalProjectCollection
        .LoadedProjects.FirstOrDefault(pr => pr.FullPath == projFilePath);

if (p == null)
    p = new Microsoft.Build.Evaluation.Project(projFilePath);

// Update instance of project
p.ReevaluateIfNecessary();

// Check folder is not already in the project
var folderLoc = @"C:\projects\BabDb\test\test2";
if(p.Items.FirstOrDefault(i => i.EvaluatedInclude == folderLoc) == null)
    p.AddItem("Folder", folderLoc);

// Check file is not already in the project
var fileLoc = @"C:\projects\BabDb\test\test2\Class1.cs";
if(p.Items.FirstOrDefault(i => i.EvaluatedInclude == fileLoc) == null)
    p.AddItem("Compile", fileLoc);

p.Save();
5
Aetbmo

Vous pouvez utiliser des modèles de texte T4. Voir http://msdn.Microsoft.com/en-us/library/vstudio/bb126445 (v = vs.100) .aspx pour plus d'informations.

0
tlango