public override async void Launch(Response response, dynamic args) { _attachMode = false; SetExceptionBreakpoints(args.__exceptionOptions); //validate argument 'program' //TODO: Remove this 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; //} XamarinOptions xamarinOptions = CreateFromArgs(args); if (!ValidateArg(response, xamarinOptions.CSProj, VSCodeKeys.XamarinOptions.CSProj)) { return; } if (!ValidateArg(response, xamarinOptions.Configuration, VSCodeKeys.XamarinOptions.Configuration)) { return; } if (!ValidateArg(response, xamarinOptions.Platform, VSCodeKeys.XamarinOptions.Platform)) { return; } int port = Utilities.FindFreePort(10000); var host = getString(args, "address"); IPAddress address = string.IsNullOrWhiteSpace(host) ? IPAddress.Loopback : Utilities.ResolveIPAddress(host); if (address == null) { SendErrorResponse(response, 3013, "Invalid address '{address}'.", new { address = address }); return; } Connect(xamarinOptions, address, port); await LaunchiOS(xamarinOptions, port); SendResponse(response); }
public async void LaunchMono(Response response, dynamic args) { _attachMode = false; SetExceptionBreakpoints(args.__exceptionOptions); // 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 '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 '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; } } const string host = "127.0.0.1"; int port = Utilities.FindFreePort(55555); string mono_path = runtimeExecutable; if (mono_path == null) { if (!Utilities.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 cmdLine = new List <String>(); bool debug = !getBool(args, "noDebug", false); if (debug) { cmdLine.Add("--debug"); cmdLine.Add(String.Format("--debugger-agent=transport=dt_socket,server=y,address={0}:{1}", host, port)); } // add 'runtimeArgs' if (args.runtimeArgs != null) { string[] runtimeArguments = args.runtimeArgs.ToObject <string[]>(); if (runtimeArguments != null && runtimeArguments.Length > 0) { cmdLine.AddRange(runtimeArguments); } } // add 'program' if (workingDirectory == null) { // if no working dir given, we use the direct folder of the executable workingDirectory = Path.GetDirectoryName(programPath); cmdLine.Add(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 cmdLine.Add(Utilities.MakeRelativePath(workingDirectory, programPath)); } // add 'args' if (args.args != null) { string[] arguments = args.args.ToObject <string[]>(); if (arguments != null && arguments.Length > 0) { cmdLine.AddRange(arguments); } } // what console? var console = getString(args, "console", null); if (console == null) { // continue to read the deprecated "externalConsole" attribute bool externalConsole = getBool(args, "externalConsole", false); if (externalConsole) { console = "externalTerminal"; } } if (console == "externalTerminal" || console == "integratedTerminal") { cmdLine.Insert(0, mono_path); var termArgs = new { kind = console == "integratedTerminal" ? "integrated" : "external", title = "Node Debug Console", cwd = workingDirectory, args = cmdLine.ToArray(), env = environmentVariables }; var resp = await SendRequest("runInTerminal", termArgs); if (!resp.success) { SendErrorResponse(response, 3011, "Cannot launch debug target in terminal ({_error}).", new { _error = resp.message }); return; } } else // internalConsole { _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 = Utilities.ConcatArgs(cmdLine.ToArray()); _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("runtime 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; } } if (debug) { Connect(IPAddress.Parse(host), port); } SendResponse(response); if (_process == null && !debug) { // we cannot track mono runtime process so terminate this session Terminate("cannot track mono runtime"); } }
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); }
public override async void Launch(Response response, dynamic args) { _attachMode = false; SetExceptionBreakpoints(args.__exceptionOptions); var launchOptions = new LaunchData(args); var valid = launchOptions.Validate(); _hotReloadManager?.SetLaunchData(launchOptions); if (!valid.success) { SendErrorResponse(response, 3002, valid.message); return; } int port = launchOptions.DebugPort; // Utilities.FindFreePort(55555); var host = getString(args, "address"); IPAddress address = string.IsNullOrWhiteSpace(host) ? IPAddress.Loopback : Utilities.ResolveIPAddress(host); if (address == null) { SendErrorResponse(response, 3013, "Invalid address '{address}'.", new { address = address }); return; } if (launchOptions.ProjectType == ProjectType.Android) { var r = LaunchAndroid(launchOptions, port); if (!r.success) { SendErrorResponse(response, 3002, r.message); return; } //Android takes a few seconds to get the debugger ready.... await Task.Delay(3000); } if (launchOptions.ProjectType == ProjectType.iOS || launchOptions.ProjectType == ProjectType.MacCatalyst) { port = Utilities.FindFreePort(55555); } Connect(launchOptions, address, port); //on IOS we need to do the connect before we launch the sim. if (launchOptions.ProjectType == ProjectType.iOS || launchOptions.ProjectType == ProjectType.MacCatalyst) { var r = launchOptions.ProjectType == ProjectType.iOS ? await LaunchiOS(response, launchOptions, port) : await LaunchCatalyst(launchOptions, port); if (!r.success) { SendErrorResponse(response, 3002, r.message); return; } SendResponse(response); return; } SendResponse(response); }
public override async void Launch(Response response, dynamic arguments) { _attachMode = false; //SetExceptionBreakpoints(args.__exceptionOptions); // validate argument 'program' string programPath = DynamicHelper.GetString(arguments, "program"); if (programPath == null) { SendErrorResponse(response, 3001, "Property 'program' is missing or empty.", null); return; } //Program.Log("Program path: {0}\r\n", programPath); programPath = ConvertClientPathToDebugger(programPath); if (!File.Exists(programPath) && !Directory.Exists(programPath)) { SendErrorResponse(response, 3002, "Program '{path}' does not exist.", new { path = programPath }); return; } // validate argument 'cwd' var workingDirectory = (string)arguments.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; } } // Todo: handle case insensitive file systems and forward slashes _script = Path.GetFullPath(programPath).Replace('/', '\\'); _code = File.ReadAllText(programPath); if ((_ast = Parse(response, _script)) == null) { return; } const string host = "127.0.0.1"; var port = Utilities.FindFreePort(55555); bool debug = !DynamicHelper.GetBool(arguments, "noDebug", false); if (debug) { Connect(IPAddress.Parse(host), port); } var termArgs = new { kind = "external", title = "Aphid Debug Console", cwd = workingDirectory, args = programPath, //env = environmentVariables }; var resp = await SendRequest("runInTerminal", termArgs); SendResponse(response); }