2012-01-05 37 views
8

カスタマイズ可能なレイヤーでソリューションを作成するコードジェネレータプロジェクトに取り組んでいます。今のところ 私はコード内のすべての要素を記述することによって.slnファイルを作成することができます。プロジェクトファイルにはこれが必要なく、MSBuildプロジェクトクラスを使用して編集できます。Webサイトプロジェクトを含むVisual Studio Solution(.sln)ファイルをプログラムで作成する方法

ウェブサイトのプロジェクトテンプレートのサポートなどを追加したいので、このようにして.slnファイルを編集するのはクールではありません。MSBuildなどのように、これを行うには良い方法があるのですか?

私はProgrammatically generate Visual Studio Solution Visual Studio SDK(ビジュアルスタジオの拡張、プラグインの作成など)を使用していますが、コードサンプルはありません。私のソリューションファイル、Webサイトのプロジェクトで事前

+3

ウェブサイトプロジェクトはあなたにとって悪いです。 Webアプリケーションプロジェクトを使用すると、MSBuildでそれらを操作できます。 – Svarog

+0

私は前に何か尋ねました:stackoverflow.com/questions/8064675/。どうやらあなたはEnvDTEを使ってそれを行うことができますが、私はそれをうまく動作させることができませんでした –

+0

プロジェクトファイルを生成するためにPremakeのようなものを使うことができましたか? http://industriousone.com/premake – eandersson

答えて

5

は、コード内のSLNファイルを作成するために、SLNToolsを使用する方法です。コードは混乱です!しかし、それは動作します!

SLN Toolsプロジェクトはプロジェクトファイルからslnファイルを作成できます。オープンソースであり、slnファイルの編集やマージのためのUIを提供します。この場合は、コアプロジェクトを使用し、プロジェクトの 'CWDev.SLNTools.Core.dll'を参照することで、面倒な(!

::)このようなコードのクラスのいくつかの部分は、ここでは示されておらず、また、SLNのような私自身のプロジェクトのいくつかのカスタムオブジェクトがあります、プロジェクトと...それは同じ名前でSLNToolsオブジェクトと誤解してはなりません。私は必要に応じてコメントしました!

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

希望します。

0

感謝をWebsitePropertiesプロジェクト部に記憶されています。 これらのプロパティは、ビルド構成に応じて入力パラメータとしてaspnet_compilerに渡されます。ウェブサイトプロジェクトを含むslnファイル内のprojectID(GUID)(この場合はC9683FA5-AABA-497F-B780-80EFC3EB81F2)を検索して、コードジェネレータによって更新/生成されるべきslnファイルの部分を探してください。

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 

あなたは(少なくとも)ProjectConfigurationPlatforms & NestedProjectsグローバル・セクションを更新する必要があります。これは私の場合に必要でした。

私はマージソリューションMsBuildタスクを実装しました。 1つのMergedSolution.slnファイルに複数のソリューションファイルをマージすることができます。これは、500以上のプロジェクト(C#&ウェブサイト& SQL DBプロジェクトファイル/セクション)を含む20以上のソリューションファイルで動作します。出力ソリューションのファイルサイズは1.3MBです。

EDIT: SLN Tools projectは、プロジェクトファイルからslnファイルを作成できます。

  • Hereがソリューションとプロジェクトファイル形式についての良い情報です:カスタムMSBuildのタスクとSLNファイルを生成する方法

  • プロジェクトファイルのセットを持っている場合は、あなたがcustom MSBuild taskによって、ソリューションファイル を生成することができます(内部メソッドを実行)
  • のMSBuildプロジェクトファイルを読むためにMicrosoft.Build.BuildEngine.Projectクラスを使用します(それは時代遅れですが、私はまだそれを使用しています)、またはMicrosoft.Build.Evaluation.Projectクラス
+0

おかげさまで、あなたはそれをすべて自分でやったのですが、道具や授業などを思いついたのですか? – Ashkan

+0

カスタムMSBuildタスクを使用していますが、ソースコードを公開できません - 会社ルール、ごめんなさい:( – Ludwo

+0

msbuildタスクで.slnファイルを作成する方法のヒントを教えてください。 – Ashkan

1

IVsSolutionインターフェイスを使用すると、ソリューションを作成してプロジェクトを追加できます。あなたはそのようにそのインターフェイスのインスタンスを取得するためにGetService()方法にSVsSolutionタイプに渡します。ここでは

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

私はこれが動作すると思います!しかし、私は視覚的な相互作用を使用する必要はありませんが、必要なものに対して正確に利用できるツールはないようです。 – Ashkan

関連する問題