gpt4 book ai didi

c# - VisualStudio 多项目模板

转载 作者:行者123 更新时间:2023-11-30 12:14:20 29 4
gpt4 key购买 nike

我正在创建一个多项目模板

问题是当我运行模板时,每个项目都会创建一个与项目名称匹配的目录文件夹。

我不希望每个项目都默认创建文件夹,如下所示:

  • solutionfolder\Libraries\BL\projectname\ 我的文件 - 和 csproj 文件
  • solutionfolder\Libraries\BL\interfaces\projectname\ 我的文件 - 和 csproj 文件

我想要的是:

  • solutionfolder\Libraries\BL\ 我的文件和csproj文件
  • solutionfolder\Libraries\BL\interfaces\ 我的文件和csproj文件

我试过了<CreateNewFolder> false </CreateNewFolder>但这不起作用

:如何在不创建项目文件夹的情况下创建项目模板?

<ProjectCollection>
<SolutionFolder Name="Libraries">
<SolutionFolder Name="BL">
<SolutionFolder Name="Interfaces">
<ProjectTemplateLink ProjectName="BL_$safeprojectname$_Interfaces">Libraries\BL\Interfaces\MyTemplate.vstemplate</ProjectTemplateLink>
</SolutionFolder>
<ProjectTemplateLink ProjectName="BL_$safeprojectname$">Libraries\BL\MyTemplate.vstemplate</ProjectTemplateLink>
</SolutionFolder>
</ProjectCollection>

最佳答案

您可以通过创建向导模板来移动文件夹和项目项。只需将逻辑放在 ProjectFinishedGenerating() 方法中。

我使用此文件作为我自己模板的引用,特别是 MoveProjectTo() 方法。

WizardImplementation.cs ( original link , cached )

using System;
using System.Collections.Generic;
using Microsoft.VisualStudio.TemplateWizard;
using VSLangProj;
using EnvDTE;
using EnvDTE80;
using System.IO;
using System.Windows.Forms;
using System.Threading;
using System.Xml;

namespace SharpArchApplicationWizard
{
// Class that implements the IWizard() interface
internal class WizardImplementation : IWizard
{
/// <summary>
/// Provide a means for sub-projects to have access to the solution name
/// </summary>
private static string solutionName;
private static string guidAssignedToCore = "{00000000-0000-0000-0000-000000000000}";
private static string guidAssignedToData = "{00000000-0000-0000-0000-000000000000}";
private static string guidAssignedToApplicationServices = "{00000000-0000-0000-0000-000000000000}";
private static string guidAssignedToControllers = "{00000000-0000-0000-0000-000000000000}";

private const int MIN_TIME_FOR_PROJECT_TO_RELEASE_FILE_LOCK = 700;
private EnvDTE._DTE dte;
private WizardRunKind runKind;
private Dictionary<string, string> replacementsDictionary;

// RunStarted() method gets called before the template wizard creates the project.
void IWizard.RunStarted(object application, Dictionary<string, string> replacementsDictionary, WizardRunKind runKind, object[] customParams) {
this.dte = application as EnvDTE._DTE;
this.runKind = runKind;
this.replacementsDictionary = replacementsDictionary;

// Store the solution name locally while processing the solution template
if (runKind == WizardRunKind.AsMultiProject) {
solutionName = replacementsDictionary["$safeprojectname$"];
}

replacementsDictionary.Add("$solutionname$", solutionName);

if (runKind == WizardRunKind.AsNewProject) {
// Make the solution root path available for all the projects
replacementsDictionary.Add("$solutionrootpath$", GetSolutionRootPath() + solutionName + "\\");

AddProjectGuidsTo(replacementsDictionary);
}
}

/// <summary>
/// Makes the project GUIDs, which are collected during the project creation process,
/// available to subsequent projects
/// </summary>
private static void AddProjectGuidsTo(Dictionary<string, string> replacementsDictionary) {
replacementsDictionary.Add("$guidAssignedToCore$", guidAssignedToCore);
replacementsDictionary.Add("$guidAssignedToData$", guidAssignedToData);
replacementsDictionary.Add("$guidAssignedToApplicationServices$", guidAssignedToApplicationServices);
replacementsDictionary.Add("$guidAssignedToControllers$", guidAssignedToControllers);
}

/// <summary>
/// Runs custom wizard logic when a project has finished generating
/// </summary>
void IWizard.ProjectFinishedGenerating(EnvDTE.Project project) {
if (project != null) {
if (project.Name == "SolutionItemsContainer") {
PerformSolutionInitialization(project);
MoveSolutionItemsToLib(project);
}
else if (project.Name == "ToolsSolutionItemsContainer") {
MoveSolutionItemsToToolsLib(project);
}
else if (project.Name == "CrudScaffolding") {
Project movedProject = MoveProjectTo("\\tools\\", project, "Code Generation");
ExcludeProjectFromBuildProcess(movedProject);
}
else if (project.Name == GetSolutionName() + ".Tests") {
MoveProjectTo("\\tests\\", project);
}
else if (project.Name == GetSolutionName() + ".Web.Controllers" ||
project.Name == GetSolutionName() + ".ApplicationServices" ||
project.Name == GetSolutionName() + ".Core" ||
project.Name == GetSolutionName() + ".Data" ||
project.Name == GetSolutionName() + ".Web") {
Project movedProject = MoveProjectTo("\\app\\", project);

// Give the solution time to release the lock on the project file
System.Threading.Thread.Sleep(MIN_TIME_FOR_PROJECT_TO_RELEASE_FILE_LOCK);

CaptureProjectGuidOf(movedProject);
}
}
}

private void CaptureProjectGuidOf(Project project) {
if (IsProjectReferredByOtherProjects(project)) {
string projectPath = GetSolutionRootPath() + GetSolutionName() + "\\app\\" + project.Name + "\\" + project.Name + ".csproj";

Log("CaptureProjectGuidOf: Does " + projectPath + " exist? " + File.Exists(projectPath).ToString());
Log("CaptureProjectGuidOf: About to open " + projectPath);

XmlDocument xmlDocument = new XmlDocument();
xmlDocument.Load(projectPath);
XmlNodeList projectGuidNodes = xmlDocument.GetElementsByTagName("ProjectGuid");

if (projectGuidNodes == null || projectGuidNodes.Count == 0)
throw new ApplicationException("Couldn't find a matching node in the project file for ProjectGuid");

StoreCapturedGuidForLaterUse(project, projectGuidNodes);

Log("CaptureProjectGuidOf: Captured the GUID " + projectGuidNodes[0].InnerText + " for " + project.Name);
}
}

private void StoreCapturedGuidForLaterUse(Project project, XmlNodeList projectGuidNodes) {
if (project.Name == GetSolutionName() + ".ApplicationServices") {
guidAssignedToApplicationServices = projectGuidNodes[0].InnerText;
}
else if (project.Name == GetSolutionName() + ".Core") {
guidAssignedToCore = projectGuidNodes[0].InnerText;
}
else if (project.Name == GetSolutionName() + ".Web.Controllers") {
guidAssignedToControllers = projectGuidNodes[0].InnerText;
}
else if (project.Name == GetSolutionName() + ".Data") {
guidAssignedToData = projectGuidNodes[0].InnerText;
}
}

private bool IsProjectReferredByOtherProjects(Project project) {
return project.Name == GetSolutionName() + ".ApplicationServices" ||
project.Name == GetSolutionName() + ".Core" ||
project.Name == GetSolutionName() + ".Web.Controllers" ||
project.Name == GetSolutionName() + ".Data";
}

/// <summary>
/// Sets up the solution structure and performs a number of related initialization steps
/// </summary>
private void PerformSolutionInitialization(EnvDTE.Project project) {
CreateSolutionDirectoryStructure();
MoveCommonAssemblyInfoToRoot(project);
}

/// <summary>
/// Runs custom wizard logic when the wizard has completed all tasks
/// </summary>
void IWizard.RunFinished() {
// Only copy the solution items once, right after processing the solution template
if (runKind == WizardRunKind.AsMultiProject) {
DeleteSuoFile();

// Operations after this must take into account that the solution path has changed
MoveSolutionFileToProjectsDirectory();
}
}

private void ExcludeProjectFromBuildProcess(EnvDTE.Project project) {
Solution2 solution = dte.Solution as Solution2;
SolutionBuild2 solutionBuild = (SolutionBuild2)solution.SolutionBuild;

foreach (SolutionConfiguration solutionConfiguration in solutionBuild.SolutionConfigurations) {
foreach (SolutionContext solutionContext in solutionConfiguration.SolutionContexts) {
if (solutionContext.ProjectName.IndexOf(project.Name) > -1) {
Log("ExcludeProjectFromBuildProcess: Setting build to false for project " + solutionContext.ProjectName +
" within the " + solutionConfiguration.Name + " configuration");
solutionContext.ShouldBuild = false;
}
}
}
}

private Project MoveProjectTo(string targetSubFolder, EnvDTE.Project project) {
return MoveProjectTo(targetSubFolder, project, null);
}

private Project MoveProjectTo(string targetSubFolder, EnvDTE.Project project, string solutionFolderName) {
string projectName = project.Name;
string originalLocation = GetSolutionRootPath() + GetSolutionName() + "\\" + projectName;

if (Directory.Exists(originalLocation)) {
Solution2 solution = dte.Solution as Solution2;

Log("MoveProjectTo: Removing " + projectName + " from solution");
solution.Remove(project);

// Give the solution time to release the lock on the project file
System.Threading.Thread.Sleep(MIN_TIME_FOR_PROJECT_TO_RELEASE_FILE_LOCK);

PerformManualProjectReplacementsTo(originalLocation + "\\" + projectName + ".csproj");

string targetLocation = GetSolutionRootPath() + GetSolutionName() + targetSubFolder + projectName;

Log("MoveProjectTo: Moving " + projectName + " from " + originalLocation + " to target location at " + targetLocation);
Directory.Move(originalLocation, targetLocation);

if (!string.IsNullOrEmpty(solutionFolderName)) {
SolutionFolder solutionFolder = (SolutionFolder)solution.AddSolutionFolder(solutionFolderName).Object;
Log("MoveProjectTo: Adding " + projectName + " to solution folder " + targetLocation);
return solutionFolder.AddFromFile(targetLocation + "\\" + projectName + ".csproj");
}
else {
Log("MoveProjectTo: Adding " + projectName + " to solution");
return solution.AddFromFile(targetLocation + "\\" + projectName + ".csproj", false);
}
}
else {
throw new ApplicationException("Couldn't find " + originalLocation + " to move");
}
}

/// <summary>
/// This does any manual value replacement on project files when it can't be handled
/// (or is being handled incorrectly by the VS templating process.
/// </summary>
private void PerformManualProjectReplacementsTo(string projectFilePath) {
if (File.Exists(projectFilePath)) {
Log("PerformManualProjectReplacementsTo: Going to PerformManualProjectReplacementsTo on " + projectFilePath);

// Open a file for reading
StreamReader streamReader;
streamReader = File.OpenText(projectFilePath);

// Now, read the entire file into a string
string contents = streamReader.ReadToEnd();
streamReader.Close();

// Write the modification into the same fil
StreamWriter streamWriter = File.CreateText(projectFilePath);
streamWriter.Write(contents.Replace("PLACE_HOLDER_COMMON_ASSEMLY_INFO_LOCATION", "..\\..\\CommonAssemblyInfo.cs"));
streamWriter.Close();
}
else {
throw new ApplicationException("Couldn't find " + projectFilePath + " to PerformManualProjectReplacementsTo");
}
}

private void MoveCommonAssemblyInfoToRoot(EnvDTE.Project solutionItemsContainerProject) {
string originalFileLocation = GetSolutionRootPath() + GetSolutionName() + "\\SolutionItemsContainer\\CommonAssemblyInfo.cs";

if (File.Exists(originalFileLocation)) {
string targetFileLocation = GetSolutionRootPath() + GetSolutionName() + "\\CommonAssemblyInfo.cs";

Log("MoveCommonAssemblyInfoToRoot: Moving CommonAssemblyInfo.cs from " + originalFileLocation + " to root at " + targetFileLocation);
File.Move(originalFileLocation, targetFileLocation);
}
else {
throw new ApplicationException("Couldn't find CommonAssemblyInfo.cs to move");
}
}

private void MoveSolutionItemsToLib(EnvDTE.Project solutionItemsContainerProject) {
string originalLocation = GetSolutionRootPath() + GetSolutionName() + "\\SolutionItemsContainer\\Solution Items";

if (Directory.Exists(originalLocation)) {
string targetLibFolder = GetSolutionRootPath() + GetSolutionName() + "\\lib";

Log("MoveSolutionItemsToLib: Moving solution items from " + originalLocation + " to lib at " + targetLibFolder);
Directory.Move(originalLocation, targetLibFolder);

Solution2 solution = dte.Solution as Solution2;
solution.Remove(solutionItemsContainerProject);
// Give the solution time to release the lock on the project file
System.Threading.Thread.Sleep(500);

Directory.Delete(GetSolutionRootPath() + GetSolutionName() + "\\SolutionItemsContainer", true);
}
else {
throw new ApplicationException("Couldn't find " + originalLocation + " to move");
}
}

private void MoveSolutionItemsToToolsLib(EnvDTE.Project toolsSolutionItemsContainerProject) {
string originalLocation = GetSolutionRootPath() + GetSolutionName() + "\\ToolsSolutionItemsContainer\\Solution Items";

if (Directory.Exists(originalLocation)) {
string targetToolsLibFolder = GetSolutionRootPath() + GetSolutionName() + "\\tools\\lib";

Log("MoveSolutionItemsToToolsLib: Moving tools solution items from " + originalLocation + " to tools lib at " + targetToolsLibFolder);
Directory.Move(originalLocation, targetToolsLibFolder);

Solution2 solution = dte.Solution as Solution2;
solution.Remove(toolsSolutionItemsContainerProject);
// Give the solution time to release the lock on the project file
System.Threading.Thread.Sleep(500);

Directory.Delete(GetSolutionRootPath() + GetSolutionName() + "\\ToolsSolutionItemsContainer", true);
}
else {
throw new ApplicationException("Couldn't find " + originalLocation + " to move");
}
}

/// <summary>
/// Note that this is called BEFORE the SLN is moved to the solution folder; therefore, we have
/// to add the solution name after the root path.
/// </summary>
private void CreateSolutionDirectoryStructure() {
Directory.CreateDirectory(GetSolutionRootPath() + GetSolutionName() + "\\app");
Directory.CreateDirectory(GetSolutionRootPath() + GetSolutionName() + "\\build");
Directory.CreateDirectory(GetSolutionRootPath() + GetSolutionName() + "\\db");
Directory.CreateDirectory(GetSolutionRootPath() + GetSolutionName() + "\\docs");
Directory.CreateDirectory(GetSolutionRootPath() + GetSolutionName() + "\\logs");
Directory.CreateDirectory(GetSolutionRootPath() + GetSolutionName() + "\\tests");
Directory.CreateDirectory(GetSolutionRootPath() + GetSolutionName() + "\\tools");
}

private void MoveSolutionFileToProjectsDirectory() {
dte.Solution.SaveAs(
GetSolutionRootPath() + GetSolutionName() + "\\" + GetSolutionFileName());
}

private void DeleteSuoFile() {
string suoFile = GetSolutionRootPath() + GetSolutionName() + ".suo";

if (File.Exists(suoFile)) {
Log("DeleteSuoFile: Deleting " + suoFile);
File.Delete(suoFile);
}
}

private void Log(string message) {
StreamWriter streamWriter = File.AppendText(GetSolutionRootPath() + GetSolutionName() + "\\logs\\" + LOG_FILE_NAME);
streamWriter.WriteLine(DateTime.Now.ToLongTimeString() + "\t" + message);
streamWriter.Close();
}

private string GetSolutionName() {
return replacementsDictionary["$solutionname$"];
}

private string GetSolutionFileName() {
return GetSolutionName() + ".sln";
}

private string GetSolutionFileFullName() {
return dte.Solution.Properties.Item("Path").Value.ToString();
}

private string GetSolutionRootPath() {
return GetSolutionFileFullName().Replace(GetSolutionFileName(), "");
}

// This method is called before opening any item which is marked for opening in the editor in the
// .vstemplate file using the "OpenInEditor" attribute.
void IWizard.BeforeOpeningFile(EnvDTE.ProjectItem projectItem) {

}

// This method is only applicable for item templates and does not get called for project templates.
void IWizard.ProjectItemFinishedGenerating(EnvDTE.ProjectItem projectItem) {
}

// This method is only applicable for item templates and does not get called for project templates.
bool IWizard.ShouldAddProjectItem(string filePath) {
return true;
}

private const string LOG_FILE_NAME = "SharpArch.VSharpArchTemplate.log";
}
}

关于c# - VisualStudio 多项目模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9792278/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com