Visual Studio provides the excellent Solution
and Project
types for working with the "normal" workflow of solutions containing any number of projects. However, what about the Solution Items folder that gets added when you add a file directly to the solution?
This is a little trickier to manage, but it is possible!
Retrieving the folder
Fortunately, Visual Studio still includes the Solution Items folder as a real project in the solution! That way, if you know about one of the items in advance, you can use:
var proj = dte.Solution.FindProjectItem(knownFile).ContainingProject;
Or if you don't have any known files:
var proj = dte.Solution.Projects.Cast<Project>().FirstOrDefault(p => p.Name == "Solution Items" || p.Kind == EnvDTE.Constants.vsProjectItemKindSolutionItems);
This should give you the Solution Items folder as a Project that you can manipulate and read as per usual.
Creating the folder
However, if the "project" doesn't exist yet, the above methods will fail. To create the Solution Items project, you will need to cast the Solution
into it's equivalent Solution2
object, with a new AddSolutionFolder()
method. That is:
Solution2 sol2 = (Solution2)dte.Solution;
var solItems = sol2.AddSolutionFolder("Solution Items");
solItems?.AddFileToProject(newFile);
Final result
Combining these two approaches we can create a simple "get or create" method for the Solution Items folder, perfect for adding build scripts, documentation and bootstrappers to!
An example is below:
internal static Project GetOrCreateSolutionItems(DTE2 dte)
{
var solItems = dte.Solution.Projects.Cast<Project>().FirstOrDefault(p => p.Name == "Solution Items" || p.Kind == EnvDTE.Constants.vsProjectItemKindSolutionItems);
if (solItems == null)
{
Solution2 sol2 = (Solution2)dte.Solution;
solItems = sol2.AddSolutionFolder("Solution Items");
dte.StatusBar.Text = $"Created Solution Items project for solution {dte.Solution.FullName}";
}
return solItems;
}