/* * On OS X make sure that /usr/local/bin is on the PATH */ public static void FixPathOnOSX() { if (Utilities.IsOSX()) { var path = System.Environment.GetEnvironmentVariable("PATH"); if (!path.Split(':').Contains(OSX_BIN_DIR)) { path += ":" + OSX_BIN_DIR; System.Environment.SetEnvironmentVariable("PATH", path); } } }
public static LaunchResult LaunchInTerminal(string directory, string runtimePath, string[] runtimeArgs, string program, string[] programArgs, Dictionary <string, string> environmentVariables) { if (Utilities.IsOSX()) { return(LaunchInTerminalOSX(directory, runtimePath, runtimeArgs, program, programArgs, environmentVariables)); } if (Utilities.IsLinux()) { return(LaunchInTerminalLinux(directory, runtimePath, runtimeArgs, program, programArgs, environmentVariables)); } if (Utilities.IsWindows()) { return(LaunchInTerminalWindows(directory, runtimePath, runtimeArgs, program, programArgs, environmentVariables)); } return(LaunchInTerminalGeneric(directory, runtimePath, runtimeArgs, program, programArgs, environmentVariables)); }
public override void Launch(Response response, dynamic args) { _attachMode = false; // validate argument 'program' string programPath = getString(args, "program"); if (programPath == null) { SendErrorResponse(response, 3001, "Property 'program' is missing or empty.", null); return; } programPath = ConvertClientPathToDebugger(programPath); if (!File.Exists(programPath) && !Directory.Exists(programPath)) { SendErrorResponse(response, 3002, "Program '{path}' does not exist.", new { path = programPath }); return; } // validate argument 'args' string[] arguments = null; if (args.args != null) { arguments = args.args.ToObject <string[]>(); if (arguments != null && arguments.Length == 0) { arguments = null; } } // validate argument 'cwd' var workingDirectory = (string)args.cwd; if (workingDirectory != null) { workingDirectory = workingDirectory.Trim(); if (workingDirectory.Length == 0) { SendErrorResponse(response, 3003, "Property 'cwd' is empty."); return; } workingDirectory = ConvertClientPathToDebugger(workingDirectory); if (!Directory.Exists(workingDirectory)) { SendErrorResponse(response, 3004, "Working directory '{path}' does not exist.", new { path = workingDirectory }); return; } } // validate argument 'runtimeExecutable' var runtimeExecutable = (string)args.runtimeExecutable; if (runtimeExecutable != null) { runtimeExecutable = runtimeExecutable.Trim(); if (runtimeExecutable.Length == 0) { SendErrorResponse(response, 3005, "Property 'runtimeExecutable' is empty."); return; } runtimeExecutable = ConvertClientPathToDebugger(runtimeExecutable); if (!File.Exists(runtimeExecutable)) { SendErrorResponse(response, 3006, "Runtime executable '{path}' does not exist.", new { path = runtimeExecutable }); return; } } // validate argument 'runtimeArgs' string[] runtimeArguments = null; if (args.runtimeArgs != null) { runtimeArguments = args.runtimeArgs.ToObject <string[]>(); if (runtimeArguments != null && runtimeArguments.Length == 0) { runtimeArguments = null; } } // validate argument 'env' Dictionary <string, string> env = null; var environmentVariables = args.env; if (environmentVariables != null) { env = new Dictionary <string, string>(); foreach (var entry in environmentVariables) { env.Add((string)entry.Name, (string)entry.Value); } if (env.Count == 0) { env = null; } } if (Utilities.IsOSX() || Utilities.IsLinux()) { const string host = "127.0.0.1"; int port = Utilities.FindFreePort(55555); string mono_path = runtimeExecutable; if (mono_path == null) { if (!Terminal.IsOnPath(MONO)) { SendErrorResponse(response, 3011, "Can't find runtime '{_runtime}' on PATH.", new { _runtime = MONO }); return; } mono_path = MONO; // try to find mono through PATH } var mono_args = new String[runtimeArguments != null ? runtimeArguments.Length + 2 : 2]; mono_args[0] = "--debug"; mono_args[1] = String.Format("--debugger-agent=transport=dt_socket,server=y,address={0}:{1}", host, port); if (runtimeArguments != null) { runtimeArguments.CopyTo(mono_args, 2); } string program; if (workingDirectory == null) { // if no working dir given, we use the direct folder of the executable workingDirectory = Path.GetDirectoryName(programPath); program = Path.GetFileName(programPath); } else { // if working dir is given and if the executable is within that folder, we make the program path relative to the working dir program = Utilities.MakeRelativePath(workingDirectory, programPath); } bool externalConsole = getBool(args, "externalConsole", false); if (externalConsole) { var result = Terminal.LaunchInTerminal(workingDirectory, mono_path, mono_args, program, arguments, env); if (!result.Success) { SendErrorResponse(response, 3012, "Can't launch terminal ({reason}).", new { reason = result.Message }); return; } } else { _process = new System.Diagnostics.Process(); _process.StartInfo.CreateNoWindow = true; _process.StartInfo.UseShellExecute = false; _process.StartInfo.WorkingDirectory = workingDirectory; _process.StartInfo.FileName = mono_path; _process.StartInfo.Arguments = string.Format("{0} {1} {2}", Terminal.ConcatArgs(mono_args), Terminal.Quote(program), Terminal.ConcatArgs(arguments)); _stdoutEOF = false; _process.StartInfo.RedirectStandardOutput = true; _process.OutputDataReceived += (object sender, System.Diagnostics.DataReceivedEventArgs e) => { if (e.Data == null) { _stdoutEOF = true; } SendOutput("stdout", e.Data); }; _stderrEOF = false; _process.StartInfo.RedirectStandardError = true; _process.ErrorDataReceived += (object sender, System.Diagnostics.DataReceivedEventArgs e) => { if (e.Data == null) { _stderrEOF = true; } SendOutput("stderr", e.Data); }; _process.EnableRaisingEvents = true; _process.Exited += (object sender, EventArgs e) => { Terminate("node process exited"); }; if (env != null) { // we cannot set the env vars on the process StartInfo because we need to set StartInfo.UseShellExecute to true at the same time. // instead we set the env vars on MonoDebug itself because we know that MonoDebug lives as long as a debug session. foreach (var entry in env) { System.Environment.SetEnvironmentVariable(entry.Key, entry.Value); } } var cmd = string.Format("{0} {1}", mono_path, _process.StartInfo.Arguments); SendOutput("console", cmd); try { _process.Start(); _process.BeginOutputReadLine(); _process.BeginErrorReadLine(); } catch (Exception e) { SendErrorResponse(response, 3012, "Can't launch terminal ({reason}).", new { reason = e.Message }); return; } } Debugger.Connect(IPAddress.Parse(host), port); } else // Generic & Windows { CommandLine.WaitForSuspend(); if (workingDirectory == null) { // if no working dir given, we use the direct folder of the executable workingDirectory = Path.GetDirectoryName(programPath); } Debugger.WorkingDirectory = workingDirectory; if (arguments != null) { string pargs = ""; foreach (var a in arguments) { if (args.Length > 0) { pargs += ' '; } pargs += Terminal.Quote(a); } Debugger.Arguments = pargs; } if (environmentVariables != null) { var dict = Debugger.EnvironmentVariables; foreach (var entry in environmentVariables) { dict.Add(entry.Key, entry.Value); } } // TODO@AW we should use the runtimeExecutable // TODO@AW we should pass runtimeArgs var file = new FileInfo(programPath); Debugger.Run(file); // TODO@AW in case of errors? } SendResponse(response); }