private void LogDebuggerErrors() { if (_errorStream != null) { while (!_streamReadPidCancellationTokenSource.IsCancellationRequested) { string line = this.GetLineFromStream(_errorStream, _streamReadPidCancellationTokenSource.Token); if (line == null) { break; } Logger?.WriteTextBlock("dbgerr:", line); } } }
/// <summary> /// Exception filter function used to report exceptions to telemetry. This **ALWAYS** returns 'true'. /// </summary> /// <param name="currentException">The current exception which is about to be caught.</param> /// <param name="logger">For logging messages</param> /// <param name="reportOnlyCorrupting">If true, only corrupting exceptions are reported</param> /// <returns>true</returns> public static bool BeforeCatch(Exception currentException, Logger logger, bool reportOnlyCorrupting) { if (reportOnlyCorrupting && !IsCorruptingException(currentException)) { return(true); // ignore non-corrupting exceptions } try { HostTelemetry.ReportCurrentException(currentException, "Microsoft.MIDebugEngine"); logger?.WriteLine("EXCEPTION: " + currentException.GetType()); logger?.WriteTextBlock("EXCEPTION: ", currentException.StackTrace); } catch { // If anything goes wrong, ignore it. We want to report the original exception, not a telemetry problem } return(true); }
public static LaunchOptions GetInstance(string registryRoot, string exePath, string args, string dir, string options, IDeviceAppLauncherEventCallback eventCallback, TargetEngine targetEngine) { if (string.IsNullOrWhiteSpace(exePath)) { throw new ArgumentNullException("exePath"); } if (string.IsNullOrWhiteSpace(options)) { throw new InvalidLaunchOptionsException(MICoreResources.Error_StringIsNullOrEmpty); } if (string.IsNullOrEmpty(registryRoot)) { throw new ArgumentNullException("registryRoot"); } Logger.WriteTextBlock("LaunchOptions", options); LaunchOptions launchOptions = null; Guid clsidLauncher = Guid.Empty; object launcherXmlOptions = null; try { using (XmlReader reader = OpenXml(options)) { switch (reader.LocalName) { case "LocalLaunchOptions": { var serializer = new Microsoft.Xml.Serialization.GeneratedAssembly.LocalLaunchOptionsSerializer(); var xmlLaunchOptions = (Xml.LaunchOptions.LocalLaunchOptions)Deserialize(serializer, reader); launchOptions = LocalLaunchOptions.CreateFromXml(xmlLaunchOptions); } break; case "SerialPortLaunchOptions": { var serializer = new Microsoft.Xml.Serialization.GeneratedAssembly.SerialPortLaunchOptionsSerializer(); var xmlLaunchOptions = (Xml.LaunchOptions.SerialPortLaunchOptions)Deserialize(serializer, reader); launchOptions = SerialLaunchOptions.CreateFromXml(xmlLaunchOptions); } break; case "PipeLaunchOptions": { var serializer = new Microsoft.Xml.Serialization.GeneratedAssembly.PipeLaunchOptionsSerializer(); var xmlLaunchOptions = (Xml.LaunchOptions.PipeLaunchOptions)Deserialize(serializer, reader); launchOptions = PipeLaunchOptions.CreateFromXml(xmlLaunchOptions); } break; case "TcpLaunchOptions": { var serializer = new Microsoft.Xml.Serialization.GeneratedAssembly.TcpLaunchOptionsSerializer(); var xmlLaunchOptions = (Xml.LaunchOptions.TcpLaunchOptions)Deserialize(serializer, reader); launchOptions = TcpLaunchOptions.CreateFromXml(xmlLaunchOptions); } break; case "IOSLaunchOptions": { var serializer = new Microsoft.Xml.Serialization.GeneratedAssembly.IOSLaunchOptionsSerializer(); launcherXmlOptions = Deserialize(serializer, reader); clsidLauncher = new Guid("316783D1-1824-4847-B3D3-FB048960EDCF"); } break; case "AndroidLaunchOptions": { var serializer = new Microsoft.Xml.Serialization.GeneratedAssembly.AndroidLaunchOptionsSerializer(); launcherXmlOptions = Deserialize(serializer, reader); clsidLauncher = new Guid("C9A403DA-D3AA-4632-A572-E81FF6301E9B"); } break; default: { throw new XmlException(string.Format(CultureInfo.CurrentCulture, MICoreResources.Error_UnknownXmlElement, reader.LocalName)); } } // Read any remaining bits of XML to catch other errors while (reader.NodeType != XmlNodeType.None) { reader.Read(); } } } catch (XmlException e) { throw new InvalidLaunchOptionsException(e.Message); } if (clsidLauncher != Guid.Empty) { launchOptions = ExecuteLauncher(registryRoot, clsidLauncher, exePath, args, dir, launcherXmlOptions, eventCallback, targetEngine); } if (targetEngine == TargetEngine.Native) { if (launchOptions.ExePath == null) { launchOptions.ExePath = exePath; } } if (string.IsNullOrEmpty(launchOptions.ExeArguments)) { launchOptions.ExeArguments = args; } if (string.IsNullOrEmpty(launchOptions.WorkingDirectory)) { launchOptions.WorkingDirectory = dir; } if (launchOptions._setupCommands == null) { launchOptions._setupCommands = new List <LaunchCommand>(capacity: 0).AsReadOnly(); } launchOptions._initializationComplete = true; return(launchOptions); }
public override async void Init(ITransportCallback transportCallback, LaunchOptions options, Logger logger, HostWaitLoop waitLoop = null) { LocalLaunchOptions localOptions = options as LocalLaunchOptions; Encoding encNoBom = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false); string commandPipeName; string outputPipeName; string pidPipeName; List <string> cmdArgs = new List <string>(); string windowtitle = FormattableString.Invariant($"cppdbg: {Path.GetFileName(options.ExePath)}"); if (PlatformUtilities.IsWindows()) { // Create Windows Named pipes commandPipeName = Utilities.GetMIEngineTemporaryFilename("In"); outputPipeName = Utilities.GetMIEngineTemporaryFilename("Out"); pidPipeName = Utilities.GetMIEngineTemporaryFilename("Pid"); string errorPipeName = Utilities.GetMIEngineTemporaryFilename("Error"); NamedPipeServerStream inputToDebugger = new NamedPipeServerStream(commandPipeName, PipeDirection.Out, 1, PipeTransmissionMode.Byte); NamedPipeServerStream outputFromDebugger = new NamedPipeServerStream(outputPipeName, PipeDirection.In, 1, PipeTransmissionMode.Byte); NamedPipeServerStream errorFromDebugger = new NamedPipeServerStream(errorPipeName, PipeDirection.In, 1, PipeTransmissionMode.Byte); NamedPipeServerStream pidPipe = new NamedPipeServerStream(pidPipeName, PipeDirection.In, 1, PipeTransmissionMode.Byte); _pidReader = new StreamReader(pidPipe, encNoBom, false, UnixUtilities.StreamBufferSize); string thisModulePath = typeof(RunInTerminalTransport).GetTypeInfo().Assembly.ManifestModule.FullyQualifiedName; string launchCommand = Path.Combine(Path.GetDirectoryName(thisModulePath), "WindowsDebugLauncher.exe"); if (!File.Exists(launchCommand)) { string errorMessage = string.Format(CultureInfo.CurrentCulture, MICoreResources.Error_InternalFileMissing, launchCommand); transportCallback.OnStdErrorLine(errorMessage); transportCallback.OnDebuggerProcessExit(null); return; } cmdArgs.Add(launchCommand); cmdArgs.Add("--stdin=" + commandPipeName); cmdArgs.Add("--stdout=" + outputPipeName); cmdArgs.Add("--stderr=" + errorPipeName); cmdArgs.Add("--pid=" + pidPipeName); cmdArgs.Add("--dbgExe=" + localOptions.MIDebuggerPath); cmdArgs.Add(localOptions.GetMiDebuggerArgs()); _waitForConnection = Task.WhenAll( inputToDebugger.WaitForConnectionAsync(), outputFromDebugger.WaitForConnectionAsync(), errorFromDebugger.WaitForConnectionAsync(), pidPipe.WaitForConnectionAsync()); _commandStream = new StreamWriter(inputToDebugger, encNoBom); _outputStream = new StreamReader(outputFromDebugger, encNoBom, false, UnixUtilities.StreamBufferSize); _errorStream = new StreamReader(errorFromDebugger, encNoBom, false, UnixUtilities.StreamBufferSize); } else { // Do Linux style pipes commandPipeName = UnixUtilities.MakeFifo(identifier: "In", logger: logger); outputPipeName = UnixUtilities.MakeFifo(identifier: "Out", logger: logger); pidPipeName = UnixUtilities.MakeFifo(identifier: "Pid", logger: logger); // Create filestreams FileStream stdInStream = new FileStream(commandPipeName, FileMode.Open); FileStream stdOutStream = new FileStream(outputPipeName, FileMode.Open); _pidReader = new StreamReader(new FileStream(pidPipeName, FileMode.Open), encNoBom, false, UnixUtilities.StreamBufferSize); string debuggerCmd = UnixUtilities.GetDebuggerCommand(localOptions); // Default working directory is next to the app string debuggeeDir; if (Path.IsPathRooted(options.ExePath) && File.Exists(options.ExePath)) { debuggeeDir = Path.GetDirectoryName(options.ExePath); } else { // If we don't know where the app is, default to HOME, and if we somehow can't get that, go with the root directory. debuggeeDir = Environment.GetEnvironmentVariable("HOME"); if (string.IsNullOrEmpty(debuggeeDir)) { debuggeeDir = "/"; } } string dbgCmdScript = Path.Combine(Path.GetTempPath(), Utilities.GetMIEngineTemporaryFilename(identifier: "Cmd")); string launchDebuggerCommand = UnixUtilities.LaunchLocalDebuggerCommand( debuggeeDir, commandPipeName, outputPipeName, pidPipeName, dbgCmdScript, debuggerCmd, localOptions.GetMiDebuggerArgs()); logger?.WriteTextBlock("DbgCmd:", launchDebuggerCommand); using (FileStream dbgCmdStream = new FileStream(dbgCmdScript, FileMode.CreateNew)) using (StreamWriter dbgCmdWriter = new StreamWriter(dbgCmdStream, encNoBom) { AutoFlush = true }) { dbgCmdWriter.WriteLine("#!/bin/sh"); dbgCmdWriter.Write(launchDebuggerCommand); dbgCmdWriter.Flush(); } if (PlatformUtilities.IsOSX()) { string osxLaunchScript = GetOSXLaunchScript(); // Call osascript with a path to the AppleScript. The apple script takes 2 parameters: a title for the terminal and the launch script. cmdArgs.Add("/usr/bin/osascript"); cmdArgs.Add(osxLaunchScript); cmdArgs.Add(FormattableString.Invariant($"\"{windowtitle}\"")); cmdArgs.Add(FormattableString.Invariant($"sh {dbgCmdScript} ;")); // needs a semicolon because this command is running through the launchscript. } else { cmdArgs.Add("sh"); cmdArgs.Add(dbgCmdScript); } _outputStream = new StreamReader(stdOutStream, encNoBom, false, UnixUtilities.StreamBufferSize); _commandStream = new StreamWriter(stdInStream, encNoBom); } RunInTerminalLauncher launcher = new RunInTerminalLauncher(windowtitle, localOptions.Environment); launcher.Launch( cmdArgs, localOptions.UseExternalConsole, LaunchSuccess, (error) => { transportCallback.OnStdErrorLine(error); throw new InvalidOperationException(error); }, logger); logger?.WriteLine("Wait for connection completion."); if (_waitForConnection != null) { // Add a timeout for waiting for connection - 20 seconds Task waitOrTimeout = Task.WhenAny(_waitForConnection, Task.Delay(20000)); await waitOrTimeout; if (waitOrTimeout.Status != TaskStatus.RanToCompletion) { string errorMessage = String.Format(CultureInfo.CurrentCulture, MICoreResources.Error_DebuggerInitializeFailed_NoStdErr, "WindowsDebugLauncher.exe"); transportCallback.OnStdErrorLine(errorMessage); transportCallback.OnDebuggerProcessExit(null); return; } } base.Init(transportCallback, options, logger, waitLoop); }