我正在开发一个代码生成器项目,该项目使用可自定义的层创建解决方案。 现在我可以通过编写代码中的所有元素来创建.sln文件。但是项目文件不需要这个,可以使用MSBuild Project类编辑它们。
我想添加一个网站项目模板支持等,所以这样我编辑.sln文件并不酷,我想知道有更好的方法来做这个,比如MSBuild或其他什么?
我看到Programmatically generate Visual Studio Solution说使用Visual Studio SDK(用于扩展visual studio,编写插件......),但没有任何代码示例。
提前致谢
答案 0 :(得分:6)
以下是如何使用SLNTools 在代码中创建sln文件。代码很乱!但它的确有效!
SLN Tools项目能够从项目文件创建sln文件。它是开源的,它提供了用于编辑和合并sln文件的UI。在这种情况下,您可以使用核心项目,并在项目中引用“CWDev.SLNTools.Core.dll”,您可以编写一个凌乱的(!)代码,如下所示:
注意:这里没有显示类的某些部分,还有我自己的项目的一些自定义对象,如Sln,Project和...,不应该与具有相同名称的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;
}
}
希望它有所帮助。
答案 1 :(得分:1)
您可以使用IVsSolution界面创建解决方案并向其添加项目。您将SVsSolution类型传递给GetService()方法以获取该接口的实例,如下所示:
var solution = (IVsSolution)GetService(typeof(SVsSolution));
答案 2 :(得分: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&amp; NestedProjects全局部分。这在我的案例中是必要的。
我已经实现了合并解决方案MsBuild任务。它支持将多个解决方案文件合并到一个MergedSolution.sln文件中。它适用于包含500多个项目的20多个解决方案文件(c#&amp; website&amp; sql db project files / sections)。输出解决方案文件大小为1.3MB :)
编辑: SLN Tools project能够从项目文件创建sln文件。
如何使用自定义MSBuild任务生成SLN文件: