2012-01-05 16 views
8

Sto lavorando a un progetto di generatore di codice che crea una soluzione con livelli personalizzabili. per ora sono in grado di creare il file .sln scrivendo tutti gli elementi nel codice. ma i file di progetto non ne hanno bisogno, possono essere modificati usando la classe MSBuild Project.Come creare i file di Visual Studio Solution (.sln) a livello di codice, compresi i progetti di siti Web?

Desidero aggiungere un supporto per modello di progetto Sito Web ed ecc. In questo modo, il file .sln non è bello, volevo sapere che c'è un modo migliore per farlo, come MSBuild o qualcos'altro?

Ho visto Programmatically generate Visual Studio Solution che dice di usare Visual Studio SDK (che è per estendere lo studio visivo, scrivere plugin ...), ma non c'è alcun esempio di codice.

grazie in anticipo

+3

I progetti di siti Web fanno male a te. Utilizzare i progetti di applicazioni Web e quelli possono essere manipolati con MSBuild di sicuro. – Svarog

+0

Ho chiesto qualcosa di simile prima: stackoverflow.com/questions/8064675/. Apparentemente puoi farlo usando EnvDTE, ma ho avuto difficoltà a farlo funzionare –

+0

Forse potresti usare qualcosa come Premake per generare i file di progetto? http://industriousone.com/premake – eandersson

risposta

5

Ecco come utilizzare SLNTools creare il file SLN nel codice. Il codice è un disastro! Ma funziona!

Il progetto SLN Tools è in grado di creare file sln dai file di progetto. È open source e fornisce un'interfaccia utente per la modifica e l'unione di file sln. In questo caso puoi utilizzare il progetto principale e facendo riferimento al file "CWDev.SLNTools.Core.dll" nel tuo progetto puoi scrivere un messaggio disordinato (!) Codice come questo:

NOTA: Alcune parti della classe non sono mostrati qui e anche ci sono alcune oggetti personalizzati del mio progetto come Sln, Progetto e ... che non deve essere confusa con SLNTools oggetti con lo stesso nome . Ho commentato dove serve!

using CWDev.SLNTools.Core; 
using SlnFile = CWDev.SLNTools.Core.SolutionFile; 
using SlnProject = CWDev.SLNTools.Core.Project; 
using SeptaCodeGenerator.Core.IO; 

public class SlnFileManager 
{ 
    // * Note: Sln is of my own type. 
    Sln _sln; 
    // * SolutionFile is the type in SLNTools project that we use 
    SlnFile _slnFile; 

    public void WriteNewSlnFile(Sln slnObject) 
    { 
     _sln = slnObject; 
     _slnFile = new SlnFile(); // or you can read sln file like below 
     using (SolutionFileReader reader = new SolutionFileReader(_sln.ObjectFullPath)) 
      _slnFile = reader.ReadSolutionFile(); 
     AddHeaders(); 
     AddGlobalSections(); 
     // add projects 
     List<SolutionNode> sns = _sln.GetAllSubItemsOf(typeof(SolutionFolder), typeof(ProjectNode)); 
     foreach (SolutionNode sn in sns) 
      _slnFile.Projects.Add(CreateProject(sn)); 

     using (SolutionFileWriter writer = new SolutionFileWriter(_sln.ObjectFullPath)) 
      writer.WriteSolutionFile(_slnFile); 
    } 

    // this is how I create and add project sections, using Section and PropertyLine 
    private SlnProject CreateProject(SolutionNode sn) 
    { 
     List<Section> projectSections = CreateProjectSections(sn); 
     List<PropertyLine> versionControlLines = CreateVersionControlLines(sn); 
     List<PropertyLine> projectConfigurationPlatformsLines = CreateProjectConfigurationPlatformsLines(sn); 

     string parentGuid = (sn.Parent is Sln ? null : sn.Parent.InstanceGuidSt); 
     string relativePath = (sn is Project) ? (sn as Project).ProjFile.ObjectRelativePath : sn.ObjectRelativePath; 
     return new CWDev.SLNTools.Core.Project(_slnFile, sn.InstanceGuidSt, sn.TypeGuidSt, sn.Name, relativePath, parentGuid, 
      projectSections, versionControlLines, projectConfigurationPlatformsLines); 
    } 

    // this method creates ProjectSections(WebsiteProperties) 
    private List<Section> CreateProjectSections(SolutionNode project) 
    { 
     Section sec = null; 
     var lines = new List<PropertyLine>(); 
     if (project is SolutionFolder) 
     { 
      List<SolutionNode> files = project.GetAllSubItemsOf(typeof(SolutionFile)); 
      foreach (SolutionNode item in files) 
      { 
       // * consideration required 
       lines.Add(new PropertyLine(item.ObjectRelativePath, item.ObjectRelativePath)); 
      } 
      if (lines.Count > 0) 
       sec = new Section("SolutionItems", "ProjectSection", "preProject", lines); 
     } 
     // *** here is the code that I wrote to add website projects *** 
     else if (project is WebSiteProject) 
     { 
      var website = project as WebSiteProject; 
      if (_sln.IsUnderSourceControl) 
      { 
        lines.AddRange(new PropertyLine[] 
        { 
         new PropertyLine("SccProjectName", "\"SAK\""), 
         new PropertyLine("SccAuxPath", "\"SAK\""), 
         new PropertyLine("SccLocalPath", "\"SAK\""), 
         new PropertyLine("SccProvider", "\"SAK\"") 
        }); 

      } 
      if (_sln.SolutionVersion == SolutionFileVersion.V11VS2010) 
       lines.Add(new PropertyLine("TargetFrameworkMoniker", "\".NETFramework,Version%3Dv4.0\"")); 
      else 
       lines.Add(new PropertyLine("TargetFramework", "\"3.5\"")); 
      // add project references 
      string projectReferences = ""; 
      foreach (Project proj in website.ReferencedProjects) 
       projectReferences += proj.InstanceGuidSt + "|" + proj.ClassName + ".dll;"; 
      lines.Add(new PropertyLine("ProjectReferences", "\"" + projectReferences + "\"")); 

      string debugConf = "Debug.AspNetCompiler."; 
      string releaseConf = "Release.AspNetCompiler."; 
      string str = debugConf; 
      int k = 0; 
      while (k < 2) 
      { 
       // other properties 
       lines.AddRange(new PropertyLine[] 
       { 
        new PropertyLine(str + "VirtualPath", "\"/" + website.Name + "\""), 
        new PropertyLine(str + "PhysicalPath", "\"" + website.ObjectRelativePath + "\\\""), 
        new PropertyLine(str + "TargetPath", ("\"PrecompiledWeb\\" + website.Name + "\\\"")), 
        new PropertyLine(str + "Updateable", "\"true\""), 
        new PropertyLine(str + "ForceOverwrite", "\"true\""), 
        new PropertyLine(str + "FixedNames", "\"false\""), 
        new PropertyLine(str + "Debug", (k == 0 ? "\"True\"" : "\"False\"")) 
       }); 

       if (k++ == 0) 
        str = releaseConf; 
      } 
      Random rand = new Random(); 
      lines.Add(new PropertyLine("VWDPort", "\"" + rand.Next(1111, 65000).ToString() + "\"")); 
      lines.Add(new PropertyLine("DefaultWebSiteLanguage", 
       website.Language == SeptaCodeGenerator.Core.Language.CodeLanguage.CSharp ? "\"Visual C#\"" : "\"Visual Basic\"")); 

      sec = new Section("WebsiteProperties", "ProjectSection", "preProject", lines); 
     } 
     var sections = new List<Section>(); 
     if (sec != null) 
      sections.Add(sec); 
     return sections; 
    } 
} 

Spero che sia d'aiuto.

0

Nei miei file di soluzione, i progetti di siti web sono memorizzati nella sezione WebsiteProperties progetto. Queste proprietà vengono passate in aspnet_compiler come parametri di input in base alla configurazione di build. Prova a cercare projectID (GUID) (C9683FA5-AABA-497F-B780-80EFC3EB81F2 in questo caso) all'interno dei tuoi file sln contenenti il ​​progetto del sito web, quali parti del file sln devono essere aggiornate/generate dal tuo generatore di codice.

Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "MasterData.Host", "..\..\Customs.Framework\Services\MasterDataService\Tests\MasterData.Host", "{C9683FA5-AABA-497F-B780-80EFC3EB81F2}" 
    ProjectSection(WebsiteProperties) = preProject 
     SccProjectName = "SAK" 
     SccAuxPath = "SAK" 
     SccLocalPath = "SAK" 
     SccProvider = "SAK" 
     TargetFrameworkMoniker = ".NETFramework,Version%3Dv3.5" 
     ProjectReferences = "{C7C785E8-89E6-459A-969C-BFC2BC7E8ED2}|Porthus.Customs.Framework.Services.MasterData.ServiceImplementation.dll;{ADFA3898-854C-4058-8726-523EA8802FFD}|Porthus.Customs.Framework.Services.MasterData.FaultContracts.dll;{9A565742-4843-40A6-A2E3-2B432573D12B}|Porthus.Customs.Framework.Services.MasterData.MessageContracts.dll;{E8B5D2A1-E934-4C85-AB71-A2148050913A}|Porthus.Customs.Framework.Services.MasterData.ServiceContracts.dll;{3C752087-CED2-499F-AF3B-84E1548229CB}|Porthus.Customs.Services.MasterData.BusinessEntities.dll;{437C651C-3C8D-4B3D-B967-E58DBCD83EE4}|Porthus.Customs.Services.MasterData.BusinessLogic.dll;{59BBDE80-6F20-4FB6-A65B-68BC584AD2CB}|Porthus.Customs.Services.MasterData.DataAccess.dll;" 
     Debug.AspNetCompiler.VirtualPath = "/MasterData.Host" 
     Debug.AspNetCompiler.PhysicalPath = "..\..\Customs.Framework\Services\MasterDataService\Tests\MasterData.Host\" 
     Debug.AspNetCompiler.TargetPath = "PrecompiledWeb\MasterData.Host\" 
     Debug.AspNetCompiler.Updateable = "true" 
     Debug.AspNetCompiler.ForceOverwrite = "true" 
     Debug.AspNetCompiler.FixedNames = "false" 
     Debug.AspNetCompiler.Debug = "True" 
     Release.AspNetCompiler.VirtualPath = "/MasterData.Host" 
     Release.AspNetCompiler.PhysicalPath = "..\..\Customs.Framework\Services\MasterDataService\Tests\MasterData.Host\" 
     Release.AspNetCompiler.TargetPath = "PrecompiledWeb\MasterData.Host\" 
     Release.AspNetCompiler.Updateable = "true" 
     Release.AspNetCompiler.ForceOverwrite = "true" 
     Release.AspNetCompiler.FixedNames = "false" 
     Release.AspNetCompiler.Debug = "False" 
     VWDPort = "1333" 
     DefaultWebSiteLanguage = "Visual C#" 
    EndProjectSection 
EndProject 

è necessario aggiornare (almeno) ProjectConfigurationPlatforms & NestedProjects sezioni globali. Questo era necessario nel mio caso.

Ho implementato l'operazione MsBuild della soluzione di unione. Supporta la fusione di più file di soluzione in un file MergedSolution.sln. Funziona con i nostri 20 o più file di soluzione contenenti più di 500 progetti (C# & sito web & sql db file di progetto/sezioni). La dimensione del file della soluzione di output è 1,3 MB :)

MODIFICA: SLN Tools project è in grado di creare il file sln dai file di progetto.

Come generare il file SLN con l'abitudine compito MSBuild:

  • Here è buono informazioni sui file di progetto soluzione e il formato.
  • Se si dispone di una serie di file di progetto, è possibile generare il file di soluzione da custom MSBuild task (metodo all'interno Execute)
  • Per leggere i file di progetto MSBuild utilizzano Microsoft.Build.BuildEngine.Project classe (è obsoleto ma sto ancora usando) o Classe Microsoft.Build.Evaluation.Project
+0

grazie, hai fatto tutto da solo, hai inventato uno strumento, una lezione o qualcosa del genere? – Ashkan

+0

Utilizzo attività MSBuild personalizzata, ma non riesco a pubblicare codice sorgente - regole aziendali, mi dispiace :( – Ludwo

+0

Sì, certo, puoi dare un suggerimento su come creare il file .sln con l'attività msbuild? Penso che questo sia il modo migliore per creare file sln, come faccio per i file di progetto (. ?? proj) .Se funziona, contrassegnerò questa come risposta. – Ashkan

1

È possibile utilizzare l'interfaccia IVsSolution per creare soluzioni e aggiungere progetti. Si passa in SVsSolution tipo al metodo GetService() per ottenere un'istanza di tale interfaccia in questo modo:

var solution = (IVsSolution)GetService(typeof(SVsSolution)); 
+0

Penso che funzioni! Ma non ho bisogno di usare l'interpolazione visiva, tuttavia, sembra che non ci sia uno strumento disponibile esattamente per quello di cui ho bisogno. – Ashkan

Problemi correlati