Replies: 5 comments 1 reply
-
I haven't investigated how to do it without using the https://tom.paschenda.org/blog/?p=44
|
Beta Was this translation helpful? Give feedback.
-
@GFlisch I have exactly the same problem. I want to set the startup projects of a solution via an extension. Have you found a solution? |
Beta Was this translation helpful? Give feedback.
-
I haven't found a way to do this without the
|
Beta Was this translation helpful? Give feedback.
-
Hi Awesome. I was waiting this from a while. It works also for me like a charm. I have in my project also extension methods on the Solution and Project objects. I have just added the 2 and I think it will be great that they integrate this in the Community edition.. I have added another method to add one project to the existing list.
What I am now looking for is to change the Action from Start to Start Without Debugging... Thanks @jamesc-skyward . |
Beta Was this translation helpful? Give feedback.
-
I've been doing a bit of investigation on this and after looking into the inner workings of Visual Studio's internal assemblies, I've come to the conclusion that it's not possible to do this without using the DTE. 😢 As @GFlisch points out, using the DTE always sets the startup mode to "Start" (which starts with debugging). There is no public way to set the mode to "Start without debugging". However, it can be done via reflection! 🎉 Here's an extension method that will set the startup projects and set whether they should start with or without debugging. I've made it an extension method on public static class StartupProjectExtensions
{
private static MethodInfo? _getProjectFromHierarchy;
private static FieldInfo? _dwStartupOpt;
public static async Task SetStartupProjectsAsync(this Solutions _, IEnumerable<(Project Project, ProjectStartupMode Mode)> projects)
{
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
// Start by setting the startup projects via the DTE.
IVsSolution solution = await VS.Services.GetSolutionAsync();
List<string> startupProjects = new();
List<object> withoutDebugging = new();
foreach ((Project Project, ProjectStartupMode Mode) item in projects)
{
item.Project.GetItemInfo(out IVsHierarchy hierarchy, out uint itemId, out IVsHierarchyItem hierarchyItem);
solution.GetUniqueNameOfProject(hierarchy, out string name);
startupProjects.Add(name);
// Setting the startup projects via the DTE will _always_ set the
// startup mode to start with debugging. If the proejct should
// be started without debugging, then we need to alter the internal
// field after the startup projects have been set. Get the internal
// project object that the field is stored on while we have the hierarchy.
if (item.Mode == ProjectStartupMode.Start)
{
withoutDebugging.Add(GetProjectFromHierarchy(solution, hierarchy));
}
}
EnvDTE.DTE dte = await VS.GetRequiredServiceAsync<EnvDTE.DTE, EnvDTE.DTE>();
dte.Solution.SolutionBuild.StartupProjects = startupProjects.ToArray();
// If any projects need to start without debugging,
// then change their internal fields now.
foreach (object project in withoutDebugging)
{
SetStartupMode(project, 2u); // 1 = With Debugging; 2 = Without debugging.
}
}
private static object GetProjectFromHierarchy(IVsSolution solution, IVsHierarchy hierarchy)
{
_getProjectFromHierarchy ??= solution.GetType().GetMethod("GetProjectFromHierarchy", BindingFlags.NonPublic | BindingFlags.Instance);
return _getProjectFromHierarchy.Invoke(solution, new object[] { hierarchy });
}
private static void SetStartupMode(object project, uint mode)
{
_dwStartupOpt ??= project.GetType().GetField("m_dwStartupOpt", BindingFlags.Public | BindingFlags.Instance);
uint option = (uint)_dwStartupOpt.GetValue(project);
// The startup mode is stored in the lower byte:
// 0 = None
// 1 = Start with Debugging
// 2 = Start
// Clear the lower two bits and set the given mode.
_dwStartupOpt.SetValue(project, (option & ~3u) | mode);
}
}
public enum ProjectStartupMode
{
StartWithDebugging,
Start
} Example usage: await VS.Solutions.SetStartupProjectsAsync(
new[] {
(await VS.Solutions.FindProjectsAsync("Primary"), ProjectStartupMode.StartWithDebugging),
(await VS.Solutions.FindProjectsAsync("Secondary"), ProjectStartupMode.Start)
}
); Because this uses the DTE and reflection, don't expect it to end up in the toolkit. 🤣 |
Beta Was this translation helpful? Give feedback.
-
Do you have an example or an idea how I can add a Project in the Multiple Startup Project list available via the Properties of a Solution?
Thanks,
Gilles
Beta Was this translation helpful? Give feedback.
All reactions