2012-01-05 91 views
8

Estoy trabajando en un proyecto generador de código que crea una solución con capas personalizables. por ahora puedo crear el archivo .sln escribiendo todos los elementos en el código. pero los archivos del proyecto no necesitan esto, pueden ser editados usando la clase MSBuild Project.¿Cómo crear archivos de Visual Studio Solution (.sln) de forma programática, incluidos los proyectos del sitio web?

Quiero agregar un soporte de plantilla de proyecto de sitio web y etc., así que de esta manera edito el archivo .sln no es genial, quería saber que hay una mejor manera de hacerlo, como MSBuild o algo más?

Vi Programmatically generate Visual Studio Solution que dice usar Visual Studio SDK (que es para ampliar Visual Studio, escribir complementos ...), pero no hay ningún ejemplo de código.

gracias de antemano

+3

Los proyectos del sitio web son malos para usted. Use proyectos de aplicaciones web, y esos pueden ser manipulados con MSBuild de seguro. – Svarog

+0

Pregunté algo similar antes: stackoverflow.com/questions/8064675/. Aparentemente puedes hacerlo usando EnvDTE, sin embargo tuve problemas para hacerlo funcionar. –

+0

¿Tal vez podrías usar algo como Premake para generar los archivos del proyecto? http://industriousone.com/premake – eandersson

Respuesta

5

Aquí es cómo utilizar SLNTools a crear el archivo sln en el código. ¡El código es un desastre! ¡Pero funciona!

El proyecto de Herramientas SLN puede crear archivos sln a partir de archivos de proyectos. Es de código abierto y proporciona UI para editar y fusionar archivos sln. En este caso, puede usar el proyecto principal y al hacer referencia al 'CWDev.SLNTools.Core.dll' en su proyecto puede escribir un mensaje desordenado (!) Código como este:

NOTA: Algunas partes de la clase no se muestran aquí y también hay algo de objetos personalizados de mi propio proyecto como Sln, Proyecto y ... que no debe confundirse con SLNTools objetos con el mismo nombre . ¡Comenté donde sea necesario!

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

Espero que ayude.

0

En mis archivos de solución, proyectos de sitios web se almacenan en la sección de proyectos WebsiteProperties. Estas propiedades se pasan al aspnet_compiler como parámetros de entrada dependiendo de la configuración de compilación. Intente buscar ID de proyecto (GUID) (C9683FA5-AABA-497F-B780-80EFC3EB81F2 en este caso) dentro de sus archivos sln que contengan un proyecto de sitio web, qué partes del archivo sln deben ser actualizadas/generadas por su generador de código.

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 

debe actualizar (al menos) ProjectConfigurationPlatforms & NestedProjects secciones globales. Esto fue necesario en mi caso.

Implementé la solución de fusión tarea MsBuild. Admite la fusión de múltiples archivos de solución en el único archivo MergedSolution.sln. Funciona en nuestros más de 20 archivos de solución que contienen más de 500 proyectos (C# & sitio web & sql db proyecto de archivos/secciones). El tamaño del archivo de solución de salida es 1.3MB :)

EDITAR: SLN Tools project es capaz de crear archivos sln a partir de archivos de proyectos.

cómo generar archivo de GLC con la costumbre tarea MSBuild:

  • Here es buena información acerca de la solución y el formato de los archivos de proyecto.
  • Si usted tiene un conjunto de archivos de proyecto, puede generar su archivo de solución por custom MSBuild task (dentro método Execute)
  • Para leer los archivos de proyecto de MSBuild utilizan Microsoft.Build.BuildEngine.Project clase (es obsoleta pero todavía estoy usando) o Microsoft.Build.Evaluation.Project class
+0

gracias, entonces lo hiciste todo por ti mismo, ¿se te ocurrió una herramienta, clase o algo así? – Ashkan

+0

Estoy usando una tarea personalizada de MSBuild, pero no puedo publicar el código fuente - reglas de la compañía, lo siento :( – Ludwo

+0

Sí, claro, ¿me puede dar una pista sobre cómo crear el archivo .sln con la tarea msbuild? Creo que esta es la mejor manera de crear archivos sln, como hago para los archivos de proyecto (. ?? proj). Si funciona, voy a marcar esto como la respuesta. – Ashkan

1

Puede usar la interfaz IVsSolution para crear soluciones y agregar proyectos a ellas. Se pasa en el tipo SVsSolution al método GetService() para obtener una instancia de esa interfaz así:

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

¡Creo que esto funciona! Pero como que no necesito usar visual sutdio interop, sin embargo, parece que no hay una herramienta disponible exactamente para lo que necesito. – Ashkan

Cuestiones relacionadas