private async Task <string> GetCommandLineForLaunchAsync() { CommandLineBuilder cb = new CommandLineBuilder(); cb.AddArguments("/waitfordebugger"); // For a known project output assembly path, this shall contain the corresponding // ConfiguredProject: Dictionary <string, ConfiguredProject> configuredProjectsByOutputAssemblyPath = new Dictionary <string, ConfiguredProject>(); // For a known ConfiguredProject, this shall contain the corresponding project output assembly // path: Dictionary <ConfiguredProject, string> outputAssemblyPathsByConfiguredProject = new Dictionary <ConfiguredProject, string>(); // Fill these two dictionaries for all projects contained in the solution // (whether they belong to the deployment or not): await ReferenceCrawler.CollectProjectsAndOutputAssemblyPathsAsync( ProjectService, configuredProjectsByOutputAssemblyPath, outputAssemblyPathsByConfiguredProject); // This HashSet shall contain a list of full paths to all assemblies to be deployed, including // the compiled output assemblies of our solution's project and also all assemblies such as // NuGet packages referenced by those projects. // The HashSet will take care of only containing any string once even if added multiple times. // However, this is dependent on getting all paths always in the same casing. // Be aware that on file systems which ignore casing, we would end up having assemblies added // more than once here if the GetFullPathAsync() methods used below should not always reliably // return the path to the same assembly in the same casing. HashSet <string> assemblyPathsToDeploy = new HashSet <string>(); // Starting with the startup project, collect all assemblies to be deployed. // This will only add assemblies of projects which are actually referenced directly or // indirectly by the startup project. Any project in the solution which is not referenced // directly or indirectly by the startup project will not be included in the list of assemblies // to be deployed. await ReferenceCrawler.CollectAssembliesToDeployAsync( configuredProjectsByOutputAssemblyPath, outputAssemblyPathsByConfiguredProject, assemblyPathsToDeploy, Properties.ConfiguredProject); // build a list with the full path for each DLL, referenced DLL and EXE List <string> assemblyList = new List <string>(); foreach (string assemblyPath in assemblyPathsToDeploy) { assemblyList.Add(assemblyPath); } // if there are referenced project, the assembly list contains repeated assemblies so need to use Linq Distinct() // build a list with the PE files corresponding to each DLL and EXE List <string> peCollection = assemblyList.Distinct().Select(a => a.Replace(".dll", ".pe").Replace(".exe", ".pe")).ToList(); foreach (string peFile in peCollection) { cb.AddArguments("/load:" + peFile); } string commandLine = cb.ToString(); commandLine = Environment.ExpandEnvironmentVariables(commandLine); return(commandLine); }
private async Task <string> GetCommandLineForLaunchAsync() { CommandLineBuilder cb = new CommandLineBuilder(); cb.AddArguments("/waitfordebugger"); /////////////////////////////////////////////////////// // get the list of assemblies referenced by the project var referencedAssemblies = await Properties.ConfiguredProject.Services.AssemblyReferences.GetResolvedReferencesAsync(); ////////////////////////////////////////////////////////////////////////// // get the list of other projects referenced by the project being deployed var referencedProjects = await Properties.ConfiguredProject.Services.ProjectReferences.GetResolvedReferencesAsync(); ///////////////////////////////////////////////////////// // get the target path to reach the PE for the executable //... we need to access the target path using reflection (step by step) // get type for ConfiguredProject var projSystemType = Properties.ConfiguredProject.GetType(); // get private property MSBuildProject var buildProject = projSystemType.GetTypeInfo().GetDeclaredProperty("MSBuildProject"); // get value of MSBuildProject property from ConfiguredProject object // this result is of type Microsoft.Build.Evaluation.Project var projectResult = ((System.Threading.Tasks.Task <Microsoft.Build.Evaluation.Project>)buildProject.GetValue(Properties.ConfiguredProject)); // we want the target path property var targetPath = projectResult.Result.Properties.First(p => p.Name == "TargetPath").EvaluatedValue; // build a list with the full path for each DLL, referenced DLL and EXE List <string> assemblyList = new List <string>(); foreach (IAssemblyReference reference in referencedAssemblies) { assemblyList.Add(await reference.GetFullPathAsync()); } // loop through each project that is set to build foreach (IBuildDependencyProjectReference project in referencedProjects) { if (await project.GetReferenceOutputAssemblyAsync()) { assemblyList.Add(await project.GetFullPathAsync()); } } // now add the executable to this list assemblyList.Add(targetPath); // build a list with the PE files corresponding to each DLL and EXE List <string> peCollection = assemblyList.Select(a => a.Replace(".dll", ".pe").Replace(".exe", ".pe")).ToList(); foreach (string peFile in peCollection) { cb.AddArguments("/load:" + peFile); } string commandLine = cb.ToString(); commandLine = Environment.ExpandEnvironmentVariables(commandLine); return(commandLine); }