Closed giggio closed 6 years ago
I have same problem. Also solution folders structure not saved in \MyProject.sln but it is in \MyProject\MyProject.sln. Solution in \MyProject\MyProject.sln is a clone of original solution. It has reference to template csproj file. \MyProject\ folder also contains folder with template project. One can exclude template folder as described in https://github.com/ligershark/sidewafflev2/issues/21, but solution \MyProject\MyProject.sln still contains reference to the template project. We can exclude the solution file from template too, but we will lose solution folder structure in \MyProject.sln.
@sayedihashimi Can you give us a hand here? Thanks!
@giggio Found solution. You can create custom wizard. In .template.config\template.vstemplate place custom wizard before default wizard:
<!-- Custom Wizard -->
<WizardExtension>
<Assembly>YourTemplate, Version=1.0.0.0, Culture=Neutral, PublicKeyToken=token</Assembly>
<FullClassName>YourTemplate.CustomWizard</FullClassName>
</WizardExtension>
<!-- Default Wizard -->
<WizardExtension>
<Assembly>Microsoft.VisualStudio.TemplateEngine.Wizard, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</Assembly>
<FullClassName>Microsoft.VisualStudio.TemplateEngine.Wizard.TemplateEngineWizard</FullClassName>
</WizardExtension>
Create field in custom wizard:
private string oldDestinationDirectory;
Place this to RunStarted method:
oldDestinationDirectory = replacementsDictionary["$destinationdirectory$"];
// Dirty hack here
var newDestinationDirectory = Path.Combine($"{replacementsDictionary["$destinationdirectory$"]}", @"..\");
replacementsDictionary["$destinationdirectory$"] = Path.GetFullPath(newDestinationDirectory);
in RunFinished:
Task.Run(() =>
{
if (Directory.Exists(oldDestinationDirectory))
{
Directory.Delete(oldDestinationDirectory);
}
});
You also may need to add references to System.IO and System.Threading.Tasks etc.
To exclude folder with template and original solution file you can use exclude in .template.config\template.json
"sources":[
{
"modifiers":[
{
"exclude":[
"TemplateFolder/**/*",
"SolutionFile.sln"
]
}
]
}
]
@giggio Found dirty hack for preserving folder structure in solution.
We will preserve old solution file and open it on project creation.
Remove "SolutionFile.sln" from exclude section in .template.config\template.json. In SolutionFile.sln wrap project section with project template by #if (false), #endif :
#if (false)
Project("{FAE04EC0-301F-11D3-BF4B-00C12379EFBC}") = "YourTemplateProject", "YourTemplateProject", "{41CFBEEE-FEC0-42C3-B1AF-4BF82A132113}"
EndProject
#endif
Add two wizards. One before default wizard, one after.
<!-- BeforeWizard -->
<WizardExtension>
<Assembly>YourTemplate, Version=1.0.0.0, Culture=Neutral, PublicKeyToken=token</Assembly>
<FullClassName>YourTemplate.BeforeWizard </FullClassName>
</WizardExtension>
<!-- Default Wizard -->
<WizardExtension>
<Assembly>Microsoft.VisualStudio.TemplateEngine.Wizard, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</Assembly>
<FullClassName>Microsoft.VisualStudio.TemplateEngine.Wizard.TemplateEngineWizard</FullClassName>
</WizardExtension>
<!-- AfterWizard -->
<WizardExtension>
<Assembly>YourTemplate, Version=1.0.0.0, Culture=Neutral, PublicKeyToken=token</Assembly>
<FullClassName>YourTemplate.AfterWizard </FullClassName>
</WizardExtension>
In Runstarted method of BeforeWizard place:
// Close new solution
var dte = (DTE) automationObject;
var solution = (Solution2) dte.Solution;
solution.Close();
// Delete old directory(in my case VS creating it) and change destination
var oldDestinationDirectory = replacementsDictionary["$destinationdirectory$"];
if (Directory.Exists(oldDestinationDirectory))
{
Directory.Delete(oldDestinationDirectory, true);
}
var newDestinationDirectory = Path.Combine($"{oldDestinationDirectory}", @"..\");
replacementsDictionary["$destinationdirectory$"] = Path.GetFullPath(newDestinationDirectory);
In AfterWizard:
private DTE dte;
private string destinationDirectory;
private string solutionName;
public void RunStarted(object automationObject,
Dictionary<string, string> replacementsDictionary,
WizardRunKind runKind, object[] customParams)
{
dte = (DTE) automationObject;
destinationDirectory = replacementsDictionary["$destinationdirectory$"];
solutionName = replacementsDictionary["$safeprojectname$"];
}
public void RunFinished()
{
// Open "old" solution
var solution = (Solution2) dte.Solution;
var pathToOldSolution = Path.Combine(destinationDirectory, solutionName + ".sln");
solution.Open(pathToOldSolution);
}
So, it works well but i don't know what kind of side-effects may appear with this approach.
I believe that this comment from a dev on the team addresses this issue. Can you take a look and let me know if that is what you're looking for?
@sayedihashimi it works, the physical folder structure is as expected. But I lost my solution folders from the original solution. Is there a way to get it back? BTW, it would be a good idea to share how to fix this, step by step, in a wiki, etc, that is discoberable. Or maybe bake the solution into Sidewaffle. @Advitalitum thanks for the help, but @sayedihashimi solution was simpler. Only one wizard. :)
@giggio Solution Folders are not supported. To create solution folders you'll need a custom wizard to handle creating those and placing projects inside of them.
@giggio were you able to find a solution for this using the responses above?
@tylerbhughes yes, the response from Sayed above helped: https://github.com/ligershark/sidewafflev2/issues/25#issuecomment-376288902
Great, I'll close this then since it's been resolved.
Great, but it would be nice to post a more structured guidance somewhere, probably on some docs or on the readme.
@giggio Thanks for the input. We're still working on documentation. It's just a slow process.
FYI the wiki we have in this repo is editable by all users.
@Advitalitum Did your solution work?
I want to see my solution folders As-Is in the generated projects.
How and where should we create and add these two new wizards? These should be added to the existing base SideWaffle project which will publish the template, or as an additional original VSix project, or an additional SideWaffle Vsix one?
@KKacer I can confirm that this solution works. you can take a look at my VS addon here
what I did was to create a new class library beside the packager project - to hold the wizards. (I have 2 set of wizards because my addon adds 2 different multilayered projects skeletons) then have the packager project reference the wizards project.
also, in the directory of the "main" solution - I have child directories. in each one I have a solution with a complete hierarchy of projects. each one of them is bundled differently as a template.
I hope that the source code can help you get were you need.
@avrahamcool Great! Will take a look at your project ASAP. Yeah I hope so.
@avrahamcool Watched that, awesome! the Wizard seems to be what I wanted, the result in your final distributed VSix also looks cool and as expected. Still I have some questions related to it, maybe you would like to give me a help, Can we discuss 5 minutes regarding this in Skype/Discord, ...?
Hi @KKacer I'll try to help. Let's take it to a private channel via email (can be found in my user profile)
I am having some trouble creating a multi-project template and I would like your recommendation on how to proceed, so I don't fight the tools.
What I want is that the final project structure on disk looks like this:
And I want my solution to have 2 solution folders,
src
andtest
that map to the directories on disk, with each project in the correct solution folder.Right now I created the template pack project file root folder, so the template structure looks like this:
My
template.json
is referencing the two.csproj
files correctly.I am having all sorts of trouble because of this. If I create a new project called
MyProject
I am getting an extraMyProject
folder created and I also get two.sln
files created, one on root, the other on theMyProject
directory. Only the second one actually has the solution folders. Structure ends up like this:So, how should I proceed? Is there any config I need to change? Thanks in advance.