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);
        }
Пример #2
0
        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);
        }