Esempio n. 1
0
        private async Task <IReadOnlyList <IDebugLaunchSettings> > QueryDebugTargetsAsync(DebugLaunchOptions launchOptions, ILaunchProfile activeProfile, bool validateSettings)
        {
            var launchSettings = new List <DebugLaunchSettings>();

            // Resolve the tokens in the profile
            ILaunchProfile resolvedProfile = await TokenReplacer.ReplaceTokensInProfileAsync(activeProfile);

            // For "run project", we want to launch the process if it's a console app via the command shell when
            // not debugging, except when this debug session is being launched for profiling.
            bool useCmdShell =
                IsRunProjectCommand(resolvedProfile) &&
                (launchOptions & (DebugLaunchOptions.NoDebug | DebugLaunchOptions.Profiling)) == DebugLaunchOptions.NoDebug &&
                await IsConsoleAppAsync();

            DebugLaunchSettings consoleTarget = await GetConsoleTargetForProfile(resolvedProfile, launchOptions, useCmdShell, validateSettings);

            launchSettings.Add(consoleTarget);

            return(launchSettings.ToArray());
        }
        /// <summary>
        /// When F5\Ctrl-F5 is invoked on a NoAction profile and error is thrown to the user. Typical case is trying to run a
        /// class library project
        /// </summary>
        public Task <IReadOnlyList <IDebugLaunchSettings> > QueryDebugTargetsAsync(DebugLaunchOptions launchOptions, ILaunchProfile activeProfile)
        {
            if (activeProfile.OtherSettings.TryGetValue("ErrorString", out object objErrorString) && objErrorString is string errorString)
            {
                throw new Exception(string.Format(VSResources.ErrorInProfilesFile2, Path.GetFileNameWithoutExtension(_configuredProject.UnconfiguredProject.FullPath), errorString));
            }

            throw new Exception(string.Format(VSResources.ErrorInProfilesFile, Path.GetFileNameWithoutExtension(_configuredProject.UnconfiguredProject.FullPath)));
        }
Esempio n. 3
0
 public Task <IReadOnlyList <IDebugLaunchSettings> > QueryDebugTargetsAsync(DebugLaunchOptions launchOptions, ILaunchProfile activeProfile)
 {
     return(QueryDebugTargetsAsync(launchOptions, activeProfile, validateSettings: false));
 }
Esempio n. 4
0
 /// <summary>
 /// This provider handles running the Project and empty commandName (this generally just runs the executable)
 /// </summary>
 public bool SupportsProfile(ILaunchProfile profile)
 {
     return(string.IsNullOrWhiteSpace(profile.CommandName) || IsRunProjectCommand(profile) || IsRunExecutableCommand(profile));
 }
 /// <summary>
 /// This provider handles the NoAction profile
 /// </summary>
 public bool SupportsProfile(ILaunchProfile profile)
 {
     return(string.Equals(profile.CommandName, LaunchSettingsProvider.ErrorProfileCommandName));
 }
 public LaunchCompleteCallback(IProjectThreadingService threadingService, DebugLaunchOptions launchOptions, IDebugProfileLaunchTargetsProvider?targetProfile, ILaunchProfile activeProfile)
 {
     _threadingService = threadingService;
     _launchOptions    = launchOptions;
     _targetProfile    = targetProfile;
     _activeProfile    = activeProfile;
 }
Esempio n. 7
0
 private static bool IsRunProjectCommand(ILaunchProfile profile)
 {
     return(string.Equals(profile.CommandName, LaunchSettingsProvider.RunProjectCommandName, StringComparison.OrdinalIgnoreCase));
 }
Esempio n. 8
0
        public async Task <bool> CanBeStartupProjectAsync(DebugLaunchOptions launchOptions, ILaunchProfile profile)
        {
            try
            {
                _ = await QueryDebugTargetsForDebugLaunchAsync(launchOptions, profile);
            }
            catch (ProjectNotRunnableDirectlyException)
            {
                return(false);
            }
            catch (Exception)
            {
            }

            return(true);
        }
Esempio n. 9
0
 private static bool IsRunExecutableCommand(ILaunchProfile profile)
 {
     return(string.Equals(profile.CommandName, LaunchSettingsProvider.RunExecutableCommandName, StringComparisons.LaunchProfileCommandNames));
 }
 public Task OnAfterLaunchAsync(DebugLaunchOptions launchOptions, ILaunchProfile profile) => Task.CompletedTask;
 private static bool ProfileShouldBePersisted(ILaunchProfile profile)
 {
     return(!profile.IsInMemoryObject());
 }
        /// <summary>
        /// This is called on F5 to return the list of debug targets. What we return depends on the type
        /// of project.
        /// </summary>
        private async Task <DebugLaunchSettings> GetConsoleTargetForProfile(ILaunchProfile resolvedProfile, DebugLaunchOptions launchOptions,
                                                                            bool useCmdShell)
        {
            var settings = new DebugLaunchSettings(launchOptions);

            string executable, arguments;

            string projectFolder     = Path.GetDirectoryName(UnconfiguredProject.FullPath);
            var    configuredProject = await GetConfiguredProjectForDebugAsync().ConfigureAwait(false);

            // If no working directory specified in the profile, we default to the one returned from GetRunnableProjectInformationAsync (if running
            // the project), or the project folder.
            string defaultWorkingDir = projectFolder;

            // Is this profile just running the project? If so we ignore the exe
            if (IsRunProjectCommand(resolvedProfile))
            {
                // Can't run a class library directly
                if (await GetIsClassLibraryAsync().ConfigureAwait(false))
                {
                    throw new Exception(VSResources.ProjectNotRunnableDirectly);
                }

                // Get the executable to run, the arguments and the default working directory
                var runData = await GetRunnableProjectInformationAsync(configuredProject).ConfigureAwait(false);

                executable = runData.Item1;
                arguments  = runData.Item2;
                if (!string.IsNullOrWhiteSpace(runData.Item3))
                {
                    defaultWorkingDir = runData.Item3;
                }

                if (!string.IsNullOrWhiteSpace(resolvedProfile.CommandLineArgs))
                {
                    arguments = arguments + " " + resolvedProfile.CommandLineArgs;
                }
            }
            else
            {
                executable = resolvedProfile.ExecutablePath;
                arguments  = resolvedProfile.CommandLineArgs;
            }

            string workingDir;

            if (string.IsNullOrWhiteSpace(resolvedProfile.WorkingDirectory))
            {
                workingDir = defaultWorkingDir;
            }
            else
            {
                // If the working directory is not rooted we assume it is relative to the project directory
                if (Path.IsPathRooted(resolvedProfile.WorkingDirectory))
                {
                    workingDir = resolvedProfile.WorkingDirectory;
                }
                else
                {
                    workingDir = Path.GetFullPath(Path.Combine(projectFolder, resolvedProfile.WorkingDirectory));
                }
            }

            // IF the executable is not rooted, we want to make is relative to the workingDir unless is doesn't contain
            // any path elements. In that case we are going to assume it is on the path
            if (!string.IsNullOrWhiteSpace(executable))
            {
                if (!Path.IsPathRooted(executable) && executable.IndexOf(Path.DirectorySeparatorChar) != -1)
                {
                    executable = Path.GetFullPath(Path.Combine(workingDir, executable));
                }
            }

            // Now validate the executable path and working directory exist
            ValidateSettings(executable, workingDir, resolvedProfile.Name);
            GetExeAndArguments(useCmdShell, executable, arguments, out string finalExecutable, out string finalArguments);


            // Apply environment variables.
            if (resolvedProfile.EnvironmentVariables != null && resolvedProfile.EnvironmentVariables.Count > 0)
            {
                foreach (var kvp in resolvedProfile.EnvironmentVariables)
                {
                    settings.Environment[kvp.Key] = kvp.Value;
                }
            }

            settings.Executable            = finalExecutable;
            settings.Arguments             = finalArguments;
            settings.CurrentDirectory      = workingDir;
            settings.LaunchOperation       = DebugLaunchOperation.CreateProcess;
            settings.LaunchDebugEngineGuid = await GetDebuggingEngineAsync(configuredProject).ConfigureAwait(false);

            settings.LaunchOptions = launchOptions | DebugLaunchOptions.StopDebuggingOnEnd;
            if (settings.Environment.Count > 0)
            {
                settings.LaunchOptions = settings.LaunchOptions | DebugLaunchOptions.MergeEnvironment;
            }

            return(settings);
        }
Esempio n. 13
0
 /// <summary>
 /// This provider handles running the Project and empty commandName (this generally just runs the executable)
 /// </summary>
 public bool SupportsProfile(ILaunchProfile profile)
 {
     return(string.IsNullOrWhiteSpace(profile.CommandName) ||
            profile.CommandName.Equals(LaunchSettingsProvider.RunProjectCommandName, StringComparison.OrdinalIgnoreCase) ||
            profile.CommandName.Equals(LaunchSettingsProvider.RunExecutableCommandName, StringComparison.OrdinalIgnoreCase));
 }
Esempio n. 14
0
 public static IWritableLaunchProfile ToWritableLaunchProfile(this ILaunchProfile curProfile)
 {
     return(new WritableLaunchProfile(curProfile));
 }
 public Task OnBeforeLaunchAsync(DebugLaunchOptions launchOptions, ILaunchProfile profile, IReadOnlyList <IDebugLaunchSettings> debugLaunchSettings)
 => Task.CompletedTask;
Esempio n. 16
0
        /// <summary>
        /// This is called on F5 to return the list of debug targets. What we return depends on the type
        /// of project.
        /// </summary>
        private async Task <DebugLaunchSettings> GetConsoleTargetForProfile(ILaunchProfile resolvedProfile, DebugLaunchOptions launchOptions, bool validateSettings)
        {
            var settings = new DebugLaunchSettings(launchOptions);

            string?executable, arguments;

            string            projectFolder     = Path.GetDirectoryName(_project.UnconfiguredProject.FullPath);
            ConfiguredProject?configuredProject = await GetConfiguredProjectForDebugAsync();

            Assumes.NotNull(configuredProject);

            // If no working directory specified in the profile, we default to output directory. If for some reason the output directory
            // is not specified, fall back to the project folder.
            string defaultWorkingDir = await GetOutputDirectoryAsync(configuredProject);

            if (string.IsNullOrEmpty(defaultWorkingDir))
            {
                defaultWorkingDir = projectFolder;
            }
            else
            {
                if (!Path.IsPathRooted(defaultWorkingDir))
                {
                    defaultWorkingDir = _fileSystem.GetFullPath(Path.Combine(projectFolder, defaultWorkingDir));
                }

                // If the directory at OutDir doesn't exist, fall back to the project folder
                if (!_fileSystem.DirectoryExists(defaultWorkingDir))
                {
                    defaultWorkingDir = projectFolder;
                }
            }

            // Is this profile just running the project? If so we ignore the exe
            if (IsRunProjectCommand(resolvedProfile))
            {
                // Get the executable to run, the arguments and the default working directory
                string workingDirectory;
                (executable, arguments, workingDirectory) = await GetRunnableProjectInformationAsync(configuredProject, validateSettings);

                if (!string.IsNullOrWhiteSpace(workingDirectory))
                {
                    defaultWorkingDir = workingDirectory;
                }

                if (!string.IsNullOrWhiteSpace(resolvedProfile.CommandLineArgs))
                {
                    arguments = arguments + " " + resolvedProfile.CommandLineArgs;
                }
            }
            else
            {
                executable = resolvedProfile.ExecutablePath;
                arguments  = resolvedProfile.CommandLineArgs;
            }

            string workingDir;

            if (Strings.IsNullOrWhiteSpace(resolvedProfile.WorkingDirectory))
            {
                workingDir = defaultWorkingDir;
            }
            else
            {
                // If the working directory is not rooted we assume it is relative to the project directory
                workingDir = _fileSystem.GetFullPath(Path.Combine(projectFolder, resolvedProfile.WorkingDirectory.Replace("/", "\\")));
            }

            // IF the executable is not rooted, we want to make is relative to the workingDir unless is doesn't contain
            // any path elements. In that case we are going to assume it is in the current directory of the VS process, or on
            // the environment path. If we can't find it, we just launch it as before.
            if (!Strings.IsNullOrWhiteSpace(executable))
            {
                executable = executable.Replace("/", "\\");
                if (Path.GetPathRoot(executable) == "\\")
                {
                    // Root of current drive
                    executable = _fileSystem.GetFullPath(executable);
                }
                else if (!Path.IsPathRooted(executable))
                {
                    if (executable.Contains("\\"))
                    {
                        // Combine with the working directory used by the profile
                        executable = _fileSystem.GetFullPath(Path.Combine(workingDir, executable));
                    }
                    else
                    {
                        // Try to resolve against the current working directory (for compat) and failing that, the environment path.
                        string exeName  = executable.EndsWith(".exe", StringComparisons.Paths) ? executable : executable + ".exe";
                        string fullPath = _fileSystem.GetFullPath(exeName);
                        if (_fileSystem.FileExists(fullPath))
                        {
                            executable = fullPath;
                        }
                        else
                        {
                            string?fullPathFromEnv = GetFullPathOfExeFromEnvironmentPath(exeName);
                            if (fullPathFromEnv != null)
                            {
                                executable = fullPathFromEnv;
                            }
                        }
                    }
                }
            }

            if (validateSettings)
            {
                ValidateSettings(executable, workingDir, resolvedProfile.Name);
            }

            // Apply environment variables.
            if (resolvedProfile.EnvironmentVariables != null && !resolvedProfile.EnvironmentVariables.IsEmpty)
            {
                foreach ((string key, string value) in resolvedProfile.EnvironmentVariables)
                {
                    settings.Environment[key] = value;
                }
            }

            settings.LaunchOperation       = DebugLaunchOperation.CreateProcess;
            settings.LaunchDebugEngineGuid = await GetDebuggingEngineAsync(configuredProject);

            if (resolvedProfile.IsNativeDebuggingEnabled())
            {
                settings.AdditionalDebugEngines.Add(DebuggerEngines.NativeOnlyEngine);
            }

            if (resolvedProfile.IsSqlDebuggingEnabled())
            {
                settings.AdditionalDebugEngines.Add(DebuggerEngines.SqlEngine);
            }

            if (settings.Environment.Count > 0)
            {
                settings.LaunchOptions |= DebugLaunchOptions.MergeEnvironment;
            }

            bool useCmdShell = false;

            if (await IsConsoleAppAsync())
            {
                if (await IsIntegratedConsoleEnabledAsync())
                {
                    settings.LaunchOptions |= DebugLaunchOptions.IntegratedConsole;
                }

                useCmdShell = UseCmdShellForConsoleLaunch(resolvedProfile, settings.LaunchOptions);
            }

            GetExeAndArguments(useCmdShell, executable, arguments, out string?finalExecutable, out string?finalArguments);

            settings.Executable       = finalExecutable;
            settings.Arguments        = finalArguments;
            settings.CurrentDirectory = workingDir;
            settings.Project          = _unconfiguredProjectVsServices.VsHierarchy;

            if (resolvedProfile.IsRemoteDebugEnabled())
            {
                settings.RemoteMachine = resolvedProfile.RemoteDebugMachine();

                string?remoteAuthenticationMode = resolvedProfile.RemoteAuthenticationMode();
                if (!Strings.IsNullOrEmpty(remoteAuthenticationMode))
                {
                    IRemoteAuthenticationProvider?remoteAuthenticationProvider = _remoteDebuggerAuthenticationService.FindProviderForAuthenticationMode(remoteAuthenticationMode);
                    if (remoteAuthenticationProvider != null)
                    {
                        settings.PortSupplierGuid = remoteAuthenticationProvider.PortSupplierGuid;
                    }
                }
            }

            return(settings);
        }
 /// <summary>
 /// Called just after the launch to do additional work (put up ui, do special configuration etc).
 /// </summary>
 public Task OnAfterLaunchAsync(DebugLaunchOptions launchOptions, ILaunchProfile profile)
 {
     throw new InvalidOperationException($"Wrong overload of {nameof(OnAfterLaunchAsync)} called.");
 }
Esempio n. 18
0
        /// <summary>
        /// Returns the provider which knows how to launch the profile type.
        /// </summary>
        public async Task <IDebugProfileLaunchTargetsProvider?> GetLaunchTargetsProviderAsync(ILaunchProfile profile)
        {
            // WORKAROUND: https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1152611
            await _threadingService.SwitchToUIThread();

            // We search through the imports in order to find the one which supports the profile
            foreach (Lazy <IDebugProfileLaunchTargetsProvider, IOrderPrecedenceMetadataView> provider in LaunchTargetsProviders)
            {
                if (provider.Value.SupportsProfile(profile))
                {
                    return(provider.Value);
                }
            }

            return(null);
        }
Esempio n. 19
0
        /// <summary>
        /// This is called on F5/Ctrl-F5 to return the list of debug targets.What we return depends on the type
        /// of project.
        /// </summary>
        public async Task <IReadOnlyList <IDebugLaunchSettings> > QueryDebugTargetsAsync(DebugLaunchOptions launchOptions, ILaunchProfile activeProfile)
        {
            List <DebugLaunchSettings> launchSettings = new List <DebugLaunchSettings>();

            // Resolve the tokens in the profile
            ILaunchProfile resolvedProfile = await TokenReplacer.ReplaceTokensInProfileAsync(activeProfile).ConfigureAwait(false);

            // For "run project", we want to launch the process via the command shell when not debugging, except when this debug session is being
            // launched for profiling.
            bool useCmdShell =
                IsRunProjectCommand(resolvedProfile) &&
                (launchOptions & (DebugLaunchOptions.NoDebug | DebugLaunchOptions.Profiling)) == DebugLaunchOptions.NoDebug;

            var consoleTarget = await GetConsoleTargetForProfile(resolvedProfile, launchOptions, useCmdShell).ConfigureAwait(false);

            launchSettings.Add(consoleTarget);

            return(launchSettings.ToArray());
        }
        public async Task <bool> CanBeStartupProjectAsync(DebugLaunchOptions launchOptions, ILaunchProfile profile)
        {
            if (IsRunProjectCommand(profile))
            {
                // If the profile uses the "Project" command, check that the project specifies
                // something we can run.

                ConfiguredProject?configuredProject = await GetConfiguredProjectForDebugAsync();

                Assumes.NotNull(configuredProject);
                Assumes.Present(configuredProject.Services.ProjectPropertiesProvider);

                IProjectProperties properties = configuredProject.Services.ProjectPropertiesProvider.GetCommonProperties();

                string?runCommand = await GetTargetCommandAsync(properties, validateSettings : true);

                if (string.IsNullOrWhiteSpace(runCommand))
                {
                    return(false);
                }
            }

            // Otherwise, the profile must be using the "Executable" command in which case it
            // can always be a start-up project.
            return(true);
        }
Esempio n. 21
0
        /// <summary>
        /// This is called on F5 to return the list of debug targets. What we return depends on the type
        /// of project.
        /// </summary>
        private async Task <DebugLaunchSettings> GetConsoleTargetForProfile(ILaunchProfile resolvedProfile, DebugLaunchOptions launchOptions,
                                                                            bool useCmdShell)
        {
            var settings = new DebugLaunchSettings(launchOptions);

            string executable, arguments;

            string projectFolder     = Path.GetDirectoryName(UnconfiguredProject.FullPath);
            var    configuredProject = await GetConfiguredProjectForDebugAsync().ConfigureAwait(false);

            // If no working directory specified in the profile, we default to the one returned from GetRunnableProjectInformationAsync (if running
            // the project), or the project folder.
            string defaultWorkingDir = projectFolder;

            // Is this profile just running the project? If so we ignore the exe
            if (IsRunProjectCommand(resolvedProfile))
            {
                // Can't run a class library directly
                if (await GetIsClassLibraryAsync().ConfigureAwait(false))
                {
                    throw new Exception(VSResources.ProjectNotRunnableDirectly);
                }

                // Get the executable to run, the arguments and the default working directory
                var runData = await GetRunnableProjectInformationAsync(configuredProject).ConfigureAwait(false);

                executable = runData.Item1;
                arguments  = runData.Item2;
                if (!string.IsNullOrWhiteSpace(runData.Item3))
                {
                    defaultWorkingDir = runData.Item3;
                }

                if (!string.IsNullOrWhiteSpace(resolvedProfile.CommandLineArgs))
                {
                    arguments = arguments + " " + resolvedProfile.CommandLineArgs;
                }
            }
            else
            {
                executable = resolvedProfile.ExecutablePath;
                arguments  = resolvedProfile.CommandLineArgs;
            }

            string workingDir;

            if (string.IsNullOrWhiteSpace(resolvedProfile.WorkingDirectory))
            {
                workingDir = defaultWorkingDir;
            }
            else
            {
                // If the working directory is not rooted we assume it is relative to the project directory
                workingDir = TheFileSystem.GetFullPath(Path.Combine(projectFolder, resolvedProfile.WorkingDirectory.Replace("/", "\\")));
            }

            // IF the executable is not rooted, we want to make is relative to the workingDir unless is doesn't contain
            // any path elements. In that case we are going to assume it is in the current directory of the VS process, or on
            // the environment path. If we can't find it, we just launch it as before.
            if (!string.IsNullOrWhiteSpace(executable))
            {
                executable = executable.Replace("/", "\\");
                if (Path.GetPathRoot(executable) == "\\")
                {
                    // Root of current drive
                    executable = TheFileSystem.GetFullPath(executable);
                }
                else if (!Path.IsPathRooted(executable))
                {
                    if (executable.Contains("\\"))
                    {
                        // Combine with the working directory used by the profile
                        executable = TheFileSystem.GetFullPath(Path.Combine(workingDir, executable));
                    }
                    else
                    {
                        // Try to resolve against the current working directory (for compat) and failing that, the environment path.
                        var exeName  = executable.EndsWith(".exe", StringComparison.OrdinalIgnoreCase)? executable : executable + ".exe";
                        var fullPath = TheFileSystem.GetFullPath(exeName);
                        if (TheFileSystem.FileExists(fullPath))
                        {
                            executable = fullPath;
                        }
                        else
                        {
                            fullPath = GetFullPathOfExeFromEnvironmentPath(exeName);
                            if (fullPath != null)
                            {
                                executable = fullPath;
                            }
                        }
                    }
                }
            }

            // Now validate the executable path and working directory exist
            ValidateSettings(executable, workingDir, resolvedProfile.Name);
            GetExeAndArguments(useCmdShell, executable, arguments, out string finalExecutable, out string finalArguments);

            // Apply environment variables.
            if (resolvedProfile.EnvironmentVariables != null && resolvedProfile.EnvironmentVariables.Count > 0)
            {
                foreach (var kvp in resolvedProfile.EnvironmentVariables)
                {
                    settings.Environment[kvp.Key] = kvp.Value;
                }
            }

            settings.Executable            = finalExecutable;
            settings.Arguments             = finalArguments;
            settings.CurrentDirectory      = workingDir;
            settings.LaunchOperation       = DebugLaunchOperation.CreateProcess;
            settings.LaunchDebugEngineGuid = await GetDebuggingEngineAsync(configuredProject).ConfigureAwait(false);

            if (resolvedProfile.NativeDebuggingIsEnabled())
            {
                settings.AdditionalDebugEngines.Add(DebuggerEngines.NativeOnlyEngine);
            }

            if (settings.Environment.Count > 0)
            {
                settings.LaunchOptions = settings.LaunchOptions | DebugLaunchOptions.MergeEnvironment;
            }

            return(settings);
        }
 /// <summary>
 /// This is called on F5/Ctrl-F5 to return the list of debug targets. What we return depends on the type
 /// of project.
 /// </summary>
 public async Task <IReadOnlyList <IDebugLaunchSettings> > QueryDebugTargetsAsync(DebugLaunchOptions launchOptions, ILaunchProfile activeProfile) =>
 await QueryDebugTargetsAsync(launchOptions, activeProfile, validateSettings : false) ?? throw new Exception(VSResources.ProjectNotRunnableDirectly);
Esempio n. 23
0
 /// <summary>
 /// Called just prior to launch to do additional work (put up ui, do special configuration etc).
 /// </summary>
 public Task OnBeforeLaunchAsync(DebugLaunchOptions launchOptions, ILaunchProfile profile)
 {
     return(Task.CompletedTask);
 }
        /// <summary>
        /// Returns <see langword="null"/> if the debug launch settings are <see langword="null"/>. Otherwise, the list of debug launch settings.
        /// </summary>
        private async Task <IReadOnlyList <IDebugLaunchSettings>?> QueryDebugTargetsAsync(DebugLaunchOptions launchOptions, ILaunchProfile activeProfile, bool validateSettings)
        {
            // Resolve the tokens in the profile
            ILaunchProfile resolvedProfile = await _tokenReplacer.ReplaceTokensInProfileAsync(activeProfile);

            DebugLaunchSettings?consoleTarget = await GetConsoleTargetForProfileAsync(resolvedProfile, launchOptions, validateSettings);

            return(consoleTarget == null ? null : new[] { consoleTarget });
        }
 /// <summary>
 /// Called just prior to launch to do additional work (put up ui, do special configuration etc).
 /// </summary>
 public Task OnAfterLaunchAsync(DebugLaunchOptions launchOptions, ILaunchProfile profile)
 {
     // Nothing to do here
     return(Task.CompletedTask);
 }
 private static bool IsRunProjectCommand(ILaunchProfile profile) =>
 string.Equals(profile.CommandName, LaunchSettingsProvider.RunProjectCommandName, StringComparisons.LaunchProfileCommandNames);
 /// <summary>
 /// Helper returns true if this is a profile which should be persisted. Filters out noaction profiles
 /// </summary>
 private bool ProfileShouldBePersisted(ILaunchProfile profile)
 {
     return(!string.Equals(profile.CommandName, ErrorProfileCommandName));
 }
        /// <summary>
        /// This is called on F5 to return the list of debug targets. What we return depends on the type
        /// of project.
        /// </summary>
        /// <returns><see langword="null"/> if the runnable project information is <see langword="null"/>. Otherwise, the debug launch settings.</returns>
        internal async Task <DebugLaunchSettings?> GetConsoleTargetForProfileAsync(ILaunchProfile resolvedProfile, DebugLaunchOptions launchOptions, bool validateSettings)
        {
            var settings = new DebugLaunchSettings(launchOptions);

            string?executable, arguments;

            string            projectFolder     = Path.GetDirectoryName(_project.UnconfiguredProject.FullPath) ?? string.Empty;
            ConfiguredProject?configuredProject = await GetConfiguredProjectForDebugAsync();

            Assumes.NotNull(configuredProject);

            // If no working directory specified in the profile, we default to output directory. If for some reason the output directory
            // is not specified, fall back to the project folder.
            string defaultWorkingDir = await GetOutputDirectoryAsync(configuredProject);

            if (string.IsNullOrEmpty(defaultWorkingDir))
            {
                defaultWorkingDir = projectFolder;
            }
            else
            {
                if (!Path.IsPathRooted(defaultWorkingDir))
                {
                    defaultWorkingDir = _fileSystem.GetFullPath(Path.Combine(projectFolder, defaultWorkingDir));
                }

                // If the directory at OutDir doesn't exist, fall back to the project folder
                if (!_fileSystem.DirectoryExists(defaultWorkingDir))
                {
                    defaultWorkingDir = projectFolder;
                }
            }

            string?commandLineArgs = resolvedProfile.CommandLineArgs?
                                     .Replace("\r\n", " ")
                                     .Replace("\r", " ")
                                     .Replace("\n", " ")
                                     .Replace("\\r\\n", "\r\n")
                                     .Replace("\\n", "\n");

            // Is this profile just running the project? If so we ignore the exe
            if (IsRunProjectCommand(resolvedProfile))
            {
                // Get the executable to run, the arguments and the default working directory
                (string Command, string Arguments, string WorkingDirectory)? runnableProjectInfo = await GetRunnableProjectInformationAsync(configuredProject, validateSettings);

                if (runnableProjectInfo == null)
                {
                    return(null);
                }
                string workingDirectory;
                (executable, arguments, workingDirectory) = runnableProjectInfo.Value;

                if (!string.IsNullOrWhiteSpace(workingDirectory))
                {
                    defaultWorkingDir = workingDirectory;
                }

                if (!string.IsNullOrWhiteSpace(commandLineArgs))
                {
                    arguments = arguments + " " + commandLineArgs;
                }
            }
            else
            {
                executable = resolvedProfile.ExecutablePath;
                arguments  = commandLineArgs;
            }

            string workingDir;

            if (Strings.IsNullOrWhiteSpace(resolvedProfile.WorkingDirectory))
            {
                workingDir = defaultWorkingDir;
            }
            else
            {
                // If the working directory is not rooted we assume it is relative to the project directory
                workingDir = _fileSystem.GetFullPath(Path.Combine(projectFolder, resolvedProfile.WorkingDirectory.Replace("/", "\\")));
            }

            // IF the executable is not rooted, we want to make is relative to the workingDir unless is doesn't contain
            // any path elements. In that case we are going to assume it is in the current directory of the VS process, or on
            // the environment path. If we can't find it, we just launch it as before.
            if (!Strings.IsNullOrWhiteSpace(executable))
            {
                executable = executable.Replace("/", "\\");
                if (Path.GetPathRoot(executable) == "\\")
                {
                    // Root of current drive
                    executable = _fileSystem.GetFullPath(executable);
                }
                else if (!Path.IsPathRooted(executable))
                {
                    if (executable.Contains("\\"))
                    {
                        // Combine with the working directory used by the profile
                        executable = _fileSystem.GetFullPath(Path.Combine(workingDir, executable));
                    }
                    else
                    {
                        // Try to resolve against the current working directory (for compat) and failing that, the environment path.
                        string exeName  = executable.EndsWith(".exe", StringComparisons.Paths) ? executable : executable + ".exe";
                        string fullPath = _fileSystem.GetFullPath(exeName);
                        if (_fileSystem.FileExists(fullPath))
                        {
                            executable = fullPath;
                        }
                        else
                        {
                            string?fullPathFromEnv = GetFullPathOfExeFromEnvironmentPath(exeName);
                            if (fullPathFromEnv != null)
                            {
                                executable = fullPathFromEnv;
                            }
                        }
                    }
                }
            }

            if (validateSettings)
            {
                ValidateSettings(executable, workingDir, resolvedProfile.Name);
            }

            // Apply environment variables.
            foreach ((string key, string value) in resolvedProfile.EnumerateEnvironmentVariables())
            {
                settings.Environment[key] = value;
            }

            settings.LaunchOperation       = DebugLaunchOperation.CreateProcess;
            settings.LaunchDebugEngineGuid = await GetDebuggingEngineAsync(configuredProject);

            if (resolvedProfile.IsNativeDebuggingEnabled())
            {
                settings.AdditionalDebugEngines.Add(DebuggerEngines.NativeOnlyEngine);
            }

            if (resolvedProfile.IsSqlDebuggingEnabled())
            {
                settings.AdditionalDebugEngines.Add(DebuggerEngines.SqlEngine);
            }

            bool useCmdShell = false;

            if (await _outputTypeChecker.IsConsoleAsync())
            {
                if (await IsIntegratedConsoleEnabledAsync())
                {
                    settings.LaunchOptions |= DebugLaunchOptions.IntegratedConsole;
                }

                useCmdShell = UseCmdShellForConsoleLaunch(resolvedProfile, settings.LaunchOptions);
            }

            GetExeAndArguments(useCmdShell, executable, arguments, out string?finalExecutable, out string?finalArguments);

            settings.Executable       = finalExecutable;
            settings.Arguments        = finalArguments;
            settings.CurrentDirectory = workingDir;
            settings.Project          = _unconfiguredProjectVsServices.VsHierarchy;

            if (resolvedProfile.IsRemoteDebugEnabled())
            {
                settings.RemoteMachine = resolvedProfile.RemoteDebugMachine();

                string?remoteAuthenticationMode = resolvedProfile.RemoteAuthenticationMode();
                if (!Strings.IsNullOrEmpty(remoteAuthenticationMode))
                {
                    IRemoteAuthenticationProvider?remoteAuthenticationProvider = _remoteDebuggerAuthenticationService.FindProviderForAuthenticationMode(remoteAuthenticationMode);
                    if (remoteAuthenticationProvider != null)
                    {
                        settings.PortSupplierGuid = remoteAuthenticationProvider.PortSupplierGuid;
                    }
                }
            }

            // WebView2 debugging is only supported for Project and Executable commands
            if (resolvedProfile.IsJSWebView2DebuggingEnabled() && (IsRunExecutableCommand(resolvedProfile) || IsRunProjectCommand(resolvedProfile)))
            {
                // If JS Debugger is selected, we would need to change the launch debugger to that one
                settings.LaunchDebugEngineGuid = DebuggerEngines.JavaScriptForWebView2Engine;

                // Create the launch params needed for the JS debugger
                var debuggerLaunchOptions = new JObject(
                    new JProperty("type", "pwa-msedge"),
                    new JProperty("runtimeExecutable", finalExecutable),
                    new JProperty("webRoot", workingDir),     // We use the Working Directory debugging option as the WebRoot, to map the urls to files on disk
                    new JProperty("useWebView", true),
                    new JProperty("runtimeArgs", finalArguments)
                    );

                settings.Options = JsonConvert.SerializeObject(debuggerLaunchOptions);
            }

            if (await HotReloadShouldBeEnabledAsync(resolvedProfile, launchOptions) &&
                await _hotReloadSessionManager.Value.TryCreatePendingSessionAsync(settings.Environment))
            {
                // Enable XAML Hot Reload
                settings.Environment["ENABLE_XAML_DIAGNOSTICS_SOURCE_INFO"] = "1";
            }

            if (settings.Environment.Count > 0)
            {
                settings.LaunchOptions |= DebugLaunchOptions.MergeEnvironment;
            }

            return(settings);
        }
Esempio n. 29
0
        private async Task <IReadOnlyList <IDebugLaunchSettings> > QueryDebugTargetsAsync(DebugLaunchOptions launchOptions, ILaunchProfile activeProfile, bool validateSettings)
        {
            var launchSettings = new List <DebugLaunchSettings>();

            // Resolve the tokens in the profile
            ILaunchProfile resolvedProfile = await _tokenReplacer.ReplaceTokensInProfileAsync(activeProfile);

            DebugLaunchSettings consoleTarget = await GetConsoleTargetForProfile(resolvedProfile, launchOptions, validateSettings);

            launchSettings.Add(consoleTarget);

            return(launchSettings.ToArray());
        }
Esempio n. 30
0
 internal static bool IsSnapshotDebuggerProfile(this ILaunchProfile launchProfile)
 {
     return(StringComparer.OrdinalIgnoreCase.Equals(launchProfile?.CommandName, LaunchProfileInitializer.LaunchProfileCommandName));
 }