/// <summary> /// Searchs the path variable for the first match of exeToSearchFor. Returns /// null if not found. /// </summary> public string GetFullPathOfExeFromEnvironmentPath(string exeToSearchFor) { string pathEnv = TheEnvironment.GetEnvironmentVariable("Path"); if (string.IsNullOrEmpty(pathEnv)) { return(null); } var paths = pathEnv.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries); foreach (var path in paths) { // We don't want one bad path entry to derail the search try { string exePath = Path.Combine(path, exeToSearchFor); if (TheFileSystem.FileExists(exePath)) { return(exePath); } } catch (ArgumentException) { } } return(null); }
/// <summary> /// Searches the path variable for the first match of exeToSearchFor. Returns /// null if not found. /// </summary> public string GetFullPathOfExeFromEnvironmentPath(string exeToSearchFor) { string pathEnv = TheEnvironment.GetEnvironmentVariable("Path"); if (string.IsNullOrEmpty(pathEnv)) { return(null); } foreach (string path in new LazyStringSplit(pathEnv, ';')) { // We don't want one bad path entry to derail the search try { string exePath = Path.Combine(path, exeToSearchFor); if (TheFileSystem.FileExists(exePath)) { return(exePath); } } catch (ArgumentException) { } } return(null); }
/// <summary> /// Does some basic validation of the settings. If we don't, the error messages are terrible. /// </summary> public void ValidateSettings(string executable, string workingDir, string profileName) { if (string.IsNullOrEmpty(executable)) { throw new Exception(string.Format(VSResources.NoDebugExecutableSpecified, profileName)); } else if (executable.IndexOf(Path.DirectorySeparatorChar) != -1 && !TheFileSystem.FileExists(executable)) { throw new Exception(string.Format(VSResources.DebugExecutableNotFound, executable, profileName)); } else if (!string.IsNullOrEmpty(workingDir) && !TheFileSystem.DirectoryExists(workingDir)) { throw new Exception(string.Format(VSResources.WorkingDirecotryInvalid, workingDir, profileName)); } }
/// <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 output directory. If for some reason the output directory // is not specified, fall back to the project folder. string defaultWorkingDir = await GetOutputDirectoryAsync(configuredProject).ConfigureAwait(false); if (string.IsNullOrEmpty(defaultWorkingDir)) { defaultWorkingDir = projectFolder; } else { if (!Path.IsPathRooted(defaultWorkingDir)) { defaultWorkingDir = TheFileSystem.GetFullPath(Path.Combine(projectFolder, defaultWorkingDir)); } // If the directory at OutDir doesn't exist, fall back to the project folder if (!TheFileSystem.DirectoryExists(defaultWorkingDir)) { 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); }