public override void Disconnect(Response response, dynamic args) { Log.Write($"UnityDebug: Disconnect: {args}"); Log.Write($"UnityDebug: Disconnect: {response}"); if (unityDebugConnector != null) { unityDebugConnector.OnDisconnect(); unityDebugConnector = null; } lock (m_Lock) { if (m_Session != null) { m_DebuggeeExecuting = true; m_Breakpoints = null; m_Session.Breakpoints.Clear(); m_Session.Continue(); m_Session.Detach(); m_Session.Adaptor.Dispose(); m_Session = null; } } SendOutput("stdout", "UnityDebug: Disconnected"); SetResponse(response); }
// Token: 0x06000005 RID: 5 RVA: 0x00002144 File Offset: 0x00000344 private void ConfigureSession(SoftDebuggerSession debuggerSession, IProgress <string> progress) { debuggerSession.TargetExited += delegate(object s, TargetEventArgs e) { debuggerSession.Dispose(); }; debuggerSession.OutputWriter = delegate(bool is_stderr, string text) { if (progress != null && text.Trim(new char[] { '\n', '' }).Length > 0) { progress.Report(text.TrimEnd(new char[] { '\n' })); } }; SoftDebuggerSession softDebuggerSession = debuggerSession; softDebuggerSession.ExceptionHandler = (ExceptionHandler)Delegate.Combine(softDebuggerSession.ExceptionHandler, new ExceptionHandler(delegate(Exception e) { progress.Report(e.Message); DebuggerSession.tracer.Error(e); return(true); })); debuggerSession.LogWriter = debuggerSession.OutputWriter; }
public XamarinThread(XamarinEngine engine, long id, string name, string location, SoftDebuggerSession session) { _engine = engine; _id = id; _name = name; _location = location; _session = session; }
private string SerializeDebuggerOptions(string jsonDebugOptions) { try { NLogService.TraceEnteringMethod(Logger); var debugOptions = DebugOptions.DeserializeFromJson(jsonDebugOptions); _session = new MonoDebugSession(); LogMonoDebuggerAssemblyPaths(); if (debugOptions.UserSettings.EnableVerboseDebugLogging) { RegisterEventHandlers(); } var connectionTimeout = 30000; var evaluationTimeout = 30000; var startupProject = StartupProject; XamarinEngine.DebugOptions = debugOptions; var softDebuggerConnectArgs = new SoftDebuggerConnectArgs(debugOptions.TargetExeFileName, debugOptions.GetHostIP(), debugOptions.GetMonoDebugPort()); // TODO implement programm output via stream //softDebuggerConnectArgs.RedirectOutput = true; //softDebuggerConnectArgs.OutputPort = ???; //_session.VirtualMachine.StandardOutput ??? softDebuggerConnectArgs.TimeBetweenConnectionAttempts = (int)debugOptions.UserSettings.TimeBetweenConnectionAttemptsInMs; softDebuggerConnectArgs.MaxConnectionAttempts = (int)debugOptions.UserSettings.MaxConnectionAttempts; _startInfo = new StartInfo( softDebuggerConnectArgs, new DebuggingOptions() { EvaluationTimeout = evaluationTimeout, MemberEvaluationTimeout = evaluationTimeout, ModificationTimeout = evaluationTimeout, SocketTimeout = connectionTimeout }, startupProject ); SessionMarshalling sessionMarshalling = new SessionMarshalling(_session, _startInfo); using (MemoryStream ms = new MemoryStream()) { BinaryFormatter bf = new BinaryFormatter(); ObjRef oref = RemotingServices.Marshal(sessionMarshalling); bf.Serialize(ms, oref); return(Convert.ToBase64String(ms.ToArray())); } } catch (Exception ex) { Logger.Error(ex); throw; } }
// Token: 0x06000113 RID: 275 RVA: 0x00005184 File Offset: 0x00003384 public BreakpointsAdapter(Process process, IEventSender eventSender, SoftDebuggerSession session) { this.eventSender = eventSender; this.threading = process; this.process = process; this.session = session; session.TargetHitBreakpoint += this.OnTargetHitBreakpoint; session.Breakpoints.BreakpointStatusChanged += this.OnBreakpointStatusChanged; }
// Token: 0x0600002C RID: 44 RVA: 0x000028BC File Offset: 0x00000ABC public void StartSession(StartInfo startInfo, SoftDebuggerSession session) { MonoDebuggerLauncher.tracer.Verbose("Entering Start() for: {0}", new object[] { this }); this.ConfigureSession(session, this.progress); this.debugLauncher.StartDebugger(session, startInfo); session.Run(startInfo, startInfo.SessionOptions); }
// Token: 0x06000004 RID: 4 RVA: 0x000020F0 File Offset: 0x000002F0 public DebuggerSession(StartInfo startInfo, IProgress <string> progress, SoftDebuggerSession session, IDebugLauncher debugLauncher = null) { DebuggerSession.tracer.Verbose("Entering constructor for: {0}", new object[] { this }); this.progress = progress; this.startInfo = startInfo; this.debuggerSession = session; this.debugLauncher = (debugLauncher ?? new DebugLauncher()); }
public bool StartDebugger(SoftDebuggerSession session, StartInfo startInfo) { tracer.Verbose("Entering Launch for: {0}", this); var debugger = ServiceProvider.GlobalProvider.GetService <SVsShellDebugger, IVsDebugger4>(); var sessionMarshalling = new SessionMarshalling(session, startInfo); VsDebugTargetInfo4 info = new VsDebugTargetInfo4(); info.dlo = (uint)Microsoft.VisualStudio.Shell.Interop.DEBUG_LAUNCH_OPERATION.DLO_CreateProcess; var startArgs = startInfo.StartArgs; var appName = "Mono"; if (startArgs is SoftDebuggerRemoteArgs) { appName = ((SoftDebuggerRemoteArgs)startArgs).AppName; } else if (startArgs is SoftDebuggerLaunchArgs) { appName = Path.GetFileNameWithoutExtension(startInfo.Command); } info.bstrExe = appName; info.bstrCurDir = ""; info.bstrArg = null; // no command line parameters info.bstrRemoteMachine = null; info.fSendToOutputWindow = 0; // Let stdout stay with the application. info.guidPortSupplier = Guids.PortSupplierGuid; info.guidLaunchDebugEngine = Guids.EngineGuid; info.bstrPortName = appName; using (MemoryStream ms = new MemoryStream()) { BinaryFormatter bf = new BinaryFormatter(); ObjRef oref = RemotingServices.Marshal(sessionMarshalling); bf.Serialize(ms, oref); info.bstrOptions = Convert.ToBase64String(ms.ToArray()); } try { var results = new VsDebugTargetProcessInfo[1]; debugger.LaunchDebugTargets4(1, new[] { info }, results); return(true); } catch (Exception ex) { tracer.Error("Controller.Launch ()", ex); throw; } }
public void Dispose() { if (_session == null) { return; } lock (_lock) { _session.Dispose(); _session = null; } }
// Token: 0x06000012 RID: 18 RVA: 0x0000229C File Offset: 0x0000049C public bool StartDebugger(SoftDebuggerSession session, StartInfo startInfo) { DebugLauncher.tracer.Verbose("Entering Launch for: {0}", new object[] { this }); IVsDebugger4 service = ServiceProvider.GlobalProvider.GetService <SVsShellDebugger, IVsDebugger4>(); SessionMarshalling obj = new SessionMarshalling(session, startInfo); VsDebugTargetInfo4 vsDebugTargetInfo = default(VsDebugTargetInfo4); vsDebugTargetInfo.dlo = 1U; vsDebugTargetInfo.bstrExe = "Mono"; vsDebugTargetInfo.bstrCurDir = ""; vsDebugTargetInfo.bstrArg = null; vsDebugTargetInfo.bstrRemoteMachine = null; vsDebugTargetInfo.fSendToOutputWindow = 0; vsDebugTargetInfo.guidPortSupplier = Guids.PortSupplierGuid; vsDebugTargetInfo.guidLaunchDebugEngine = Guids.EngineGuid; vsDebugTargetInfo.bstrPortName = "Mono"; using (MemoryStream memoryStream = new MemoryStream()) { BinaryFormatter binaryFormatter = new BinaryFormatter(); ObjRef graph = RemotingServices.Marshal(obj); binaryFormatter.Serialize(memoryStream, graph); vsDebugTargetInfo.bstrOptions = Convert.ToBase64String(memoryStream.ToArray()); } bool result; try { VsDebugTargetProcessInfo[] array = new VsDebugTargetProcessInfo[1]; service.LaunchDebugTargets4(1U, new VsDebugTargetInfo4[] { vsDebugTargetInfo }, array); result = true; } catch (Exception ex) { DebugLauncher.tracer.Error("Controller.Launch ()", new object[] { ex }); throw; } return(result); }
public int LaunchSuspended(string server, IDebugPort2 port, string exe, string args, string directory, string environment, string options, enum_LAUNCH_FLAGS launchFlags, uint standardInput, uint standardOutput, uint standardError, IDebugEventCallback2 callback, out IDebugProcess2 process) { processId = new AD_PROCESS_ID(); processId.ProcessIdType = (uint)enum_AD_PROCESS_ID.AD_PROCESS_ID_GUID; processId.guidProcessId = Guid.NewGuid(); EngineUtils.CheckOk(port.GetProcess(processId, out process)); this.Callback = callback; Session = new SoftDebuggerSession(); Session.TargetReady += (sender, eventArgs) => { var activeThread = Session.ActiveThread; threadManager.Add(activeThread, new MonoThread(this, activeThread)); /* * Session.Stop(); * var location = activeThread.Location; * var backtrace = activeThread.Backtrace; * var locations = Session.VirtualMachine.RootDomain.GetAssemblies().Select(x => x.Location).ToArray(); * Session.Continue(); */ MonoEngineCreateEvent.Send(this); MonoProgramCreateEvent.Send(this); }; Session.ExceptionHandler = exception => true; Session.TargetExceptionThrown += (sender, x) => Console.WriteLine(x.Type); Session.TargetExited += (sender, x) => Send(new MonoProgramDestroyEvent((uint?)x.ExitCode ?? 0), MonoProgramDestroyEvent.IID, null); Session.TargetUnhandledException += (sender, x) => Console.WriteLine(x.Type); Session.LogWriter = (stderr, text) => Console.WriteLine(text); Session.OutputWriter = (stderr, text) => Console.WriteLine(text); Session.TargetThreadStarted += (sender, x) => threadManager.Add(x.Thread, new MonoThread(this, x.Thread)); Session.TargetThreadStopped += (sender, x) => threadManager.Remove(x.Thread); Session.TargetStopped += (sender, x) => Console.WriteLine(x.Type); Session.TargetStarted += (sender, x) => Console.WriteLine(); Session.TargetSignaled += (sender, x) => Console.WriteLine(x.Type); Session.TargetInterrupted += (sender, x) => Console.WriteLine(x.Type); Session.TargetHitBreakpoint += (sender, x) => { var breakpoint = x.BreakEvent as Breakpoint; var pendingBreakpoint = breakpointManager[breakpoint]; Send(new MonoBreakpointEvent(new MonoBoundBreakpointsEnum(pendingBreakpoint.BoundBreakpoints)), MonoBreakpointEvent.IID, threadManager[x.Thread]); }; return(VSConstants.S_OK); }
protected DebuggerSession CreateSession(string test, string engineId) { var session = new SoftDebuggerSession(); session.LogWriter = (stderr, text) => { if (stderr) { Console.Error.WriteLine(text); } else { Console.Out.WriteLine(text); } }; return(session); }
void DebuggerKill() { lock (m_Lock) { if (m_Session != null) { m_DebuggeeExecuting = true; if (!m_Session.HasExited) { m_Session.Exit(); } m_Session.Dispose(); m_Session = null; } } }
public bool StartDebugger(SoftDebuggerSession session, StartInfo startInfo) { IVsDebugger4 service = ServiceProvider.GlobalProvider.GetService(typeof(SVsShellDebugger)) as IVsDebugger4; if (service == null) { return(false); } SessionMarshalling sessionMarshalling = new SessionMarshalling(session, startInfo); VsDebugTargetInfo4 debugTargetInfo4 = new VsDebugTargetInfo4 { dlo = 1U, bstrExe = string.Format("CRYENGINE - {0}", startInfo.StartupProject.Name), bstrCurDir = "", bstrArg = null, bstrRemoteMachine = null, fSendToOutputWindow = 0, guidPortSupplier = Guids.PortSupplierGuid, guidLaunchDebugEngine = Guids.EngineGuid, bstrPortName = "Mono" }; using (MemoryStream memoryStream = new MemoryStream()) { BinaryFormatter binaryFormatter = new BinaryFormatter(); ObjRef objRef = RemotingServices.Marshal(sessionMarshalling); binaryFormatter.Serialize(memoryStream, objRef); debugTargetInfo4.bstrOptions = Convert.ToBase64String(memoryStream.ToArray()); } try { VsDebugTargetProcessInfo[] pLaunchResults = new VsDebugTargetProcessInfo[1]; service.LaunchDebugTargets4(1U, new VsDebugTargetInfo4[1] { debugTargetInfo4 }, pLaunchResults); return(true); } catch { throw; } }
// Token: 0x06000167 RID: 359 RVA: 0x00005BDC File Offset: 0x00003DDC internal Process(Port port, Engine engine, IEventSender eventSender, SoftDebuggerSession session, StartInfo startInfo, string name) { this.guid = Guid.NewGuid(); this.Port = port; this.Engine = engine; this.Session = session; this.name = name; this.startInfo = startInfo; this.eventSender = eventSender; session.TargetReady += this.OnTargetReady; session.TargetExited += new EventHandler <TargetEventArgs>(this.OnTargetExited); session.TargetInterrupted += new EventHandler <TargetEventArgs>(this.OnTargetExited); session.TargetStopped += this.OnTargetPaused; session.TargetThreadStarted += this.OnThreadStart; session.TargetThreadStopped += this.OnThreadDeath; this.exceptions = new ExceptionsAdapter(this, eventSender, session); this.typeResolver = new TypeResolverAdapter(session); this.Breakpoints = new BreakpointsAdapter(this, eventSender, session); }
public static void Kill() { lock (_lock) { if (_session == null) { return; } CommandLine.InferiorExecuting = true; if (!_session.HasExited) { _session.Exit(); } _session.Dispose(); _session = null; } }
public static void Detach() { lock (_lock) { if (_session == null) { return; } CommandLine.InferiorExecuting = true; if (!_session.IsConnected) { _session.Detach(); } _session.Dispose(); _session = null; } }
public static void Disconnect() { lock (_lock) { if (_session == null) { return; } CommandLine.InferiorExecuting = true; _kind = SessionKind.Disconnected; Breakpoints.Clear(); BreakEvents.Clear(); _session.Continue(); _session = null; } }
public SoftDebugger(MonoEngine engine) { _debugEngine = engine; _options = new DebuggerSessionOptions() { EvaluationOptions = EvaluationOptions.DefaultOptions }; _options.EvaluationOptions.UseExternalTypeResolver = true; _session = new SoftDebuggerSession(); _session.Breakpoints = (_breakEvents = new BreakpointStore()); _session.TypeResolverHandler += event_TypeResolverHandler; _session.TargetReady += event_TargetReady; _session.TargetExited += event_TargetExited; _session.TargetThreadStarted += event_TargetThreadStarted; _session.TargetThreadStopped += event_TargetThreadStopped; _session.TargetHitBreakpoint += event_TargetHitBreakpoint; _session.TargetUnhandledException += event_TargetUnhandledException; }
public void Kill() { lock (_lock) { if (_session == null) { return; } if (!_session.IsRunning) { _session.Continue(); } if (!_session.HasExited) { _session.Exit(); } _session.Dispose(); _session = null; } }
private void CreateDebuggerSession() { Session = new SoftDebuggerSession(); Session.TargetReady += (sender, eventArgs) => { var activeThread = Session.ActiveThread; _threadManager.Add(activeThread, new MonoThread(_engine, activeThread)); }; Session.ExceptionHandler = e => { Log($"DEBUGGER ERROR: {e}"); return(true); }; Session.TargetThreadStarted += (sender, x) => { _threadManager.Add(x.Thread, new MonoThread(_engine, x.Thread)); }; Session.TargetThreadStopped += (sender, x) => { _threadManager.Remove(x.Thread); }; Session.TargetExited += (sender, x) => _engine.Callback.Send(new SampSharpDestroyEvent((uint?)x.ExitCode ?? 0), SampSharpDestroyEvent.Iid, null); Session.TargetExceptionThrown += (sender, args) => { _engine.Callback.Send( new MonoBreakpointEvent(new MonoBoundBreakpointsEnumerator(new IDebugBoundBreakpoint2[0])), MonoStepCompleteEvent.Iid, _threadManager[args.Thread]); }; Session.TargetHitBreakpoint += (sender, x) => { var breakpoint = x.BreakEvent as Breakpoint; var pendingBreakpoint = _breakpointManager[breakpoint]; if (pendingBreakpoint != null) { _engine.Callback.Send( new MonoBreakpointEvent(new MonoBoundBreakpointsEnumerator(pendingBreakpoint.BoundBreakpoints)), MonoBreakpointEvent.Iid, _threadManager[x.Thread]); } }; }
static void EnsureCreated() { lock (_lock) { if (_session != null) { return; } _session = new SoftDebuggerSession(); _session.Breakpoints = BreakEvents; _session.ExceptionHandler = ex => { if (Configuration.Current.LogInternalErrors) { Log.Error("Internal debugger error:", ex.GetType()); Log.Error(ex.ToString()); } return(true); }; _session.LogWriter = (isStdErr, text) => { if (Configuration.Current.LogRuntimeSpew) { Log.NoticeSameLine("[Mono] {0}", text); // The string already has a line feed. } }; _session.OutputWriter = (isStdErr, text) => { lock (Log.Lock) { if (isStdErr) { Console.Error.Write(text); } else { Console.Write(text); } } }; _session.TypeResolverHandler += (identifier, location) => { // I honestly have no idea how correct this is. I suspect you // could probably break it in some corner cases. It does make // something like `p Android.Runtime.JNIEnv.Handle` work, // though, which would otherwise have required `global::` to // be explicitly prepended. if (identifier == "__EXCEPTION_OBJECT__") { return(null); } foreach (var loc in ActiveFrame.GetAllLocals()) { if (loc.Name == identifier) { return(null); } } return(identifier); }; _session.TargetEvent += (sender, e) => { Log.Debug("Event: '{0}'", e.Type); }; _session.TargetStarted += (sender, e) => { _activeFrame = null; if (_showResumeMessage) { Log.Notice("Inferior process '{0}' ('{1}') resumed", ActiveProcess.Id, StringizeTarget()); } }; _session.TargetReady += (sender, e) => { _showResumeMessage = true; _activeProcess = _session.GetProcesses().SingleOrDefault(); // The inferior process has launched, so we can safely // set our `SIGINT` handler without it interfering with // the inferior. CommandLine.SetControlCHandler(); Log.Notice("Inferior process '{0}' ('{1}') started", ActiveProcess.Id, StringizeTarget()); }; _session.TargetStopped += (sender, e) => { Log.Notice("Inferior process '{0}' ('{1}') suspended", ActiveProcess.Id, StringizeTarget()); Log.Emphasis(Utilities.StringizeFrame(ActiveFrame, true)); CommandLine.ResumeEvent.Set(); }; _session.TargetInterrupted += (sender, e) => { Log.Notice("Inferior process '{0}' ('{1}') interrupted", ActiveProcess.Id, StringizeTarget()); Log.Emphasis(Utilities.StringizeFrame(ActiveFrame, true)); CommandLine.ResumeEvent.Set(); }; _session.TargetHitBreakpoint += (sender, e) => { var bp = e.BreakEvent as Breakpoint; var fbp = e.BreakEvent as FunctionBreakpoint; if (fbp != null) { Log.Notice("Hit method breakpoint on '{0}'", fbp.FunctionName); } else { var cond = bp.ConditionExpression != null? string.Format(" (condition '{0}' met)", bp.ConditionExpression) : string.Empty; Log.Notice("Hit breakpoint at '{0}:{1}'{2}", bp.FileName, bp.Line, cond); } Log.Emphasis(Utilities.StringizeFrame(ActiveFrame, true)); CommandLine.ResumeEvent.Set(); }; _session.TargetExited += (sender, e) => { var p = ActiveProcess; // Can happen when a remote connection attempt fails. if (p == null) { if (_kind == SessionKind.Listening) { Log.Notice("Listening socket closed"); } else if (_kind == SessionKind.Connected) { Log.Notice("Connection attempt terminated"); } else { Log.Notice("Failed to connect to '{0}'", StringizeTarget()); } } else { var code = e.ExitCode != null?string.Format(" with code '{0}'", e.ExitCode) : string.Empty; Log.Notice("Inferior process '{0}' ('{1}') exited{2}", ActiveProcess.Id, StringizeTarget(), code); } // Make sure we clean everything up on a normal exit. Kill(); _debuggeeKilled = true; _kind = SessionKind.Disconnected; CommandLine.ResumeEvent.Set(); }; _session.TargetExceptionThrown += (sender, e) => { var ex = ActiveException; Log.Notice("Trapped first-chance exception of type '{0}'", ex.Type); Log.Emphasis(Utilities.StringizeFrame(ActiveFrame, true)); PrintException(ex); CommandLine.ResumeEvent.Set(); }; _session.TargetUnhandledException += (sender, e) => { var ex = ActiveException; Log.Notice("Trapped unhandled exception of type '{0}'", ex.Type); Log.Emphasis(Utilities.StringizeFrame(ActiveFrame, true)); PrintException(ex); CommandLine.ResumeEvent.Set(); }; _session.TargetThreadStarted += (sender, e) => { Log.Notice("Inferior thread '{0}' ('{1}') started", e.Thread.Id, e.Thread.Name); }; _session.TargetThreadStopped += (sender, e) => { Log.Notice("Inferior thread '{0}' ('{1}') exited", e.Thread.Id, e.Thread.Name); }; } }
private string SerializeDebuggerOptions(string jsonDebugOptions) { DebugHelper.TraceEnteringMethod(); var debugOptions = DebugOptions.DeserializeFromJson(jsonDebugOptions); _session = new SoftDebuggerSession(); _session.TargetReady += (sender, eventArgs) => { Debug.WriteLine("TargetReady!"); }; _session.ExceptionHandler = exception => true; _session.TargetExited += (sender, x) => { Debug.WriteLine("TargetExited!"); }; _session.TargetUnhandledException += (sender, x) => { Debug.WriteLine("TargetUnhandledException!"); }; _session.LogWriter = (stderr, text) => Debug.WriteLine(text); _session.OutputWriter = (stderr, text) => Debug.WriteLine(text); _session.TargetThreadStarted += (sender, x) => Debug.WriteLine("TargetThreadStarted!"); _session.TargetThreadStopped += (sender, x) => { Debug.WriteLine("TargetThreadStopped!"); }; _session.TargetStopped += (sender, x) => Debug.WriteLine(x.Type); _session.TargetStarted += (sender, x) => Debug.WriteLine("TargetStarted"); _session.TargetSignaled += (sender, x) => Debug.WriteLine(x.Type); _session.TargetInterrupted += (sender, x) => Debug.WriteLine(x.Type); _session.TargetExceptionThrown += (sender, x) => { Debug.WriteLine("TargetExceptionThrown!"); }; _session.TargetHitBreakpoint += (sender, x) => { Debug.WriteLine("TargetHitBreakpoint!"); }; _session.TargetEvent += _session_TargetEvent; var startupProject = StartupProject; _startInfo = new StartInfo( new SoftDebuggerConnectArgs(debugOptions.TargetExeFileName, debugOptions.GetHostIP(), debugOptions.GetMonoDebugPort()), new DebuggingOptions() { EvaluationTimeout = 30000, MemberEvaluationTimeout = 30000, ModificationTimeout = 30000, SocketTimeout = 30000 }, startupProject ); SessionMarshalling sessionMarshalling = new SessionMarshalling(_session, _startInfo); using (MemoryStream ms = new MemoryStream()) { BinaryFormatter bf = new BinaryFormatter(); ObjRef oref = RemotingServices.Marshal(sessionMarshalling); bf.Serialize(ms, oref); return(Convert.ToBase64String(ms.ToArray())); } }
public UnityDebugSession() { Log.Write("Constructing UnityDebugSession"); m_ResumeEvent = new AutoResetEvent(false); m_Breakpoints = new Dictionary <string, Dictionary <int, Breakpoint> >(); m_VariableHandles = new Handles <ObjectValue[]>(); m_FrameHandles = new Handles <StackFrame>(); m_SeenThreads = new Dictionary <int, Thread>(); m_DebuggerSessionOptions = new DebuggerSessionOptions { EvaluationOptions = EvaluationOptions.DefaultOptions }; m_Session = new UnityDebuggerSession(); m_Session.Breakpoints = new BreakpointStore(); m_Catchpoints = new List <Catchpoint>(); DebuggerLoggingService.CustomLogger = new CustomLogger(); m_Session.ExceptionHandler = ex => { return(true); }; m_Session.LogWriter = (isStdErr, text) => { SendOutput(isStdErr ? "stderr" : "stdout", text); }; m_Session.TargetStopped += (sender, e) => { if (e.Backtrace != null) { Frame = e.Backtrace.GetFrame(0); } else { SendOutput("stdout", "e.Bracktrace is null"); } Stopped(); SendEvent(CreateStoppedEvent("step", e.Thread)); m_ResumeEvent.Set(); }; m_Session.TargetHitBreakpoint += (sender, e) => { Frame = e.Backtrace.GetFrame(0); Stopped(); SendEvent(CreateStoppedEvent("breakpoint", e.Thread)); m_ResumeEvent.Set(); }; m_Session.TargetExceptionThrown += (sender, e) => { Frame = e.Backtrace.GetFrame(0); for (var i = 0; i < e.Backtrace.FrameCount; i++) { if (!e.Backtrace.GetFrame(i).IsExternalCode) { Frame = e.Backtrace.GetFrame(i); break; } } Stopped(); var ex = DebuggerActiveException(); if (ex != null) { m_Exception = ex.Instance; SendEvent(CreateStoppedEvent("exception", e.Thread, ex.Message)); } m_ResumeEvent.Set(); }; m_Session.TargetUnhandledException += (sender, e) => { Stopped(); var ex = DebuggerActiveException(); if (ex != null) { m_Exception = ex.Instance; SendEvent(CreateStoppedEvent("exception", e.Thread, ex.Message)); } m_ResumeEvent.Set(); }; m_Session.TargetStarted += (sender, e) => { }; m_Session.TargetReady += (sender, e) => { m_ActiveProcess = m_Session.GetProcesses().SingleOrDefault(); }; m_Session.TargetExited += (sender, e) => { DebuggerKill(); Terminate("target exited"); m_ResumeEvent.Set(); }; m_Session.TargetInterrupted += (sender, e) => { m_ResumeEvent.Set(); }; m_Session.TargetEvent += (sender, e) => { }; m_Session.TargetThreadStarted += (sender, e) => { var tid = (int)e.Thread.Id; lock (m_SeenThreads) { m_SeenThreads[tid] = new Thread(tid, e.Thread.Name); } SendEvent(new ThreadEvent("started", tid)); }; m_Session.TargetThreadStopped += (sender, e) => { var tid = (int)e.Thread.Id; lock (m_SeenThreads) { m_SeenThreads.Remove(tid); } SendEvent(new ThreadEvent("exited", tid)); }; m_Session.OutputWriter = (isStdErr, text) => { SendOutput(isStdErr ? "stderr" : "stdout", text); }; Log.Write("Done constructing UnityDebugSession"); }
public void ApplicationRunsWithDebuggerAndBreaks(bool useSharedRuntime, bool embedAssemblies, string fastDevType) { if (!CommercialBuildAvailable) { Assert.Ignore("Test does not run on the Open Source Builds."); return; } if (!HasDevices) { Assert.Ignore("Test needs a device attached."); return; } var proj = new XamarinFormsAndroidApplicationProject() { IsRelease = false, AndroidFastDeploymentType = fastDevType }; var abis = new string [] { "armeabi-v7a", "x86" }; proj.SetProperty(KnownProperties.AndroidSupportedAbis, string.Join(";", abis)); proj.SetProperty(KnownProperties.AndroidUseSharedRuntime, useSharedRuntime.ToString()); proj.SetProperty("EmbedAssembliesIntoApk", embedAssemblies.ToString()); proj.SetDefaultTargetDevice(); using (var b = CreateApkBuilder(Path.Combine("temp", TestName))) { string apiLevel; proj.TargetFrameworkVersion = b.LatestTargetFrameworkVersion(out apiLevel); proj.AndroidManifest = $@"<?xml version=""1.0"" encoding=""utf-8""?> <manifest xmlns:android=""http://schemas.android.com/apk/res/android"" android:versionCode=""1"" android:versionName=""1.0"" package=""UnnamedProject.UnnamedProject""> <uses-sdk android:minSdkVersion=""24"" android:targetSdkVersion=""{apiLevel}"" /> <application android:label=""${{PROJECT_NAME}}""> </application > </manifest>"; b.Save(proj, saveProject: true); proj.NuGetRestore(Path.Combine(Root, b.ProjectDirectory), b.PackagesDirectory); Assert.True(b.Build(proj), "Project should have built."); Assert.True(b.Install(proj), "Project should have installed."); int breakcountHitCount = 0; ManualResetEvent resetEvent = new ManualResetEvent(false); var sw = new Stopwatch(); // setup the debugger var session = new SoftDebuggerSession(); session.Breakpoints = new BreakpointStore { { Path.Combine(Root, b.ProjectDirectory, "MainActivity.cs"), 19 }, { Path.Combine(Root, b.ProjectDirectory, "MainPage.xaml.cs"), 14 }, { Path.Combine(Root, b.ProjectDirectory, "MainPage.xaml.cs"), 19 }, { Path.Combine(Root, b.ProjectDirectory, "App.xaml.cs"), 12 }, }; session.TargetHitBreakpoint += (sender, e) => { Console.WriteLine($"BREAK {e.Type}"); breakcountHitCount++; session.Continue(); }; var rnd = new Random(); int port = rnd.Next(10000, 20000); TestContext.Out.WriteLine($"{port}"); var args = new SoftDebuggerConnectArgs("", IPAddress.Loopback, port) { MaxConnectionAttempts = 10, }; var startInfo = new SoftDebuggerStartInfo(args) { WorkingDirectory = Path.Combine(b.ProjectDirectory, proj.IntermediateOutputPath, "android", "assets"), }; var options = new DebuggerSessionOptions() { EvaluationOptions = EvaluationOptions.DefaultOptions, }; options.EvaluationOptions.UseExternalTypeResolver = true; ClearAdbLogcat(); Assert.True(b.RunTarget(proj, "_Run", parameters: new string [] { $"AndroidSdbTargetPort={port}", $"AndroidSdbHostPort={port}", "AndroidAttachDebugger=True", }), "Project should have run."); Assert.IsTrue(WaitForDebuggerToStart(output: out string logcat), "Activity should have started"); // we need to give a bit of time for the debug server to start up. WaitFor(2000); session.LogWriter += (isStderr, text) => { Console.WriteLine(text); }; session.OutputWriter += (isStderr, text) => { Console.WriteLine(text); }; session.DebugWriter += (level, category, message) => { Console.WriteLine(message); }; session.Run(startInfo, options); WaitFor(TimeSpan.FromSeconds(30), () => session.IsConnected); Assert.True(session.IsConnected, "Debugger should have connected but it did not."); // we need to wait here for a while to allow the breakpoints to hit // but we need to timeout TimeSpan timeout = TimeSpan.FromSeconds(60); while (session.IsConnected && breakcountHitCount < 3) { Thread.Sleep(10); timeout = timeout.Subtract(TimeSpan.FromMilliseconds(10)); } WaitFor(2000); ClearAdbLogcat(); ClickButton(proj.PackageName, "myXFButton", "CLICK ME"); while (session.IsConnected && breakcountHitCount < 4) { Thread.Sleep(10); timeout = timeout.Subtract(TimeSpan.FromMilliseconds(10)); } int expected = 4; Assert.AreEqual(expected, breakcountHitCount, $"Should have hit {expected} breakpoints. Only hit {breakcountHitCount}"); Assert.True(b.Uninstall(proj), "Project should have uninstalled."); session.Exit(); } }
public void ApplicationRunsWithDebuggerAndBreaks(bool useSharedRuntime, bool embedAssemblies, string fastDevType, bool allowDeltaInstall) { AssertCommercialBuild(); AssertHasDevices(); var proj = new XamarinFormsAndroidApplicationProject() { IsRelease = false, AndroidUseSharedRuntime = useSharedRuntime, EmbedAssembliesIntoApk = embedAssemblies, AndroidFastDeploymentType = fastDevType }; var abis = new string [] { "armeabi-v7a", "x86" }; proj.SetProperty(KnownProperties.AndroidSupportedAbis, string.Join(";", abis)); if (allowDeltaInstall) { proj.SetProperty(KnownProperties._AndroidAllowDeltaInstall, "true"); } proj.SetDefaultTargetDevice(); using (var b = CreateApkBuilder(Path.Combine("temp", TestName))) { SetTargetFrameworkAndManifest(proj, b); Assert.True(b.Install(proj), "Project should have installed."); int breakcountHitCount = 0; ManualResetEvent resetEvent = new ManualResetEvent(false); var sw = new Stopwatch(); // setup the debugger var session = new SoftDebuggerSession(); session.Breakpoints = new BreakpointStore { { Path.Combine(Root, b.ProjectDirectory, "MainActivity.cs"), 20 }, { Path.Combine(Root, b.ProjectDirectory, "MainPage.xaml.cs"), 14 }, { Path.Combine(Root, b.ProjectDirectory, "MainPage.xaml.cs"), 19 }, { Path.Combine(Root, b.ProjectDirectory, "App.xaml.cs"), 12 }, }; session.TargetHitBreakpoint += (sender, e) => { TestContext.WriteLine($"BREAK {e.Type}, {e.Backtrace.GetFrame (0)}"); breakcountHitCount++; session.Continue(); }; var rnd = new Random(); int port = rnd.Next(10000, 20000); TestContext.Out.WriteLine($"{port}"); var args = new SoftDebuggerConnectArgs("", IPAddress.Loopback, port) { MaxConnectionAttempts = 10, }; var startInfo = new SoftDebuggerStartInfo(args) { WorkingDirectory = Path.Combine(b.ProjectDirectory, proj.IntermediateOutputPath, "android", "assets"), }; var options = new DebuggerSessionOptions() { EvaluationOptions = EvaluationOptions.DefaultOptions, }; options.EvaluationOptions.UseExternalTypeResolver = true; ClearAdbLogcat(); Assert.True(b.RunTarget(proj, "_Run", parameters: new string [] { $"AndroidSdbTargetPort={port}", $"AndroidSdbHostPort={port}", "AndroidAttachDebugger=True", }), "Project should have run."); Assert.IsTrue(WaitForDebuggerToStart(Path.Combine(Root, b.ProjectDirectory, "logcat.log")), "Activity should have started"); // we need to give a bit of time for the debug server to start up. WaitFor(2000); session.LogWriter += (isStderr, text) => { Console.WriteLine(text); }; session.OutputWriter += (isStderr, text) => { Console.WriteLine(text); }; session.DebugWriter += (level, category, message) => { Console.WriteLine(message); }; session.Run(startInfo, options); WaitFor(TimeSpan.FromSeconds(30), () => session.IsConnected); Assert.True(session.IsConnected, "Debugger should have connected but it did not."); // we need to wait here for a while to allow the breakpoints to hit // but we need to timeout TimeSpan timeout = TimeSpan.FromSeconds(60); int expected = 3; while (session.IsConnected && breakcountHitCount < 3 && timeout >= TimeSpan.Zero) { Thread.Sleep(10); timeout = timeout.Subtract(TimeSpan.FromMilliseconds(10)); } WaitFor(2000); Assert.AreEqual(expected, breakcountHitCount, $"Should have hit {expected} breakpoints. Only hit {breakcountHitCount}"); breakcountHitCount = 0; ClearAdbLogcat(); ClickButton(proj.PackageName, "myXFButton", "CLICK ME"); while (session.IsConnected && breakcountHitCount < 1 && timeout >= TimeSpan.Zero) { Thread.Sleep(10); timeout = timeout.Subtract(TimeSpan.FromMilliseconds(10)); } expected = 1; Assert.AreEqual(expected, breakcountHitCount, $"Should have hit {expected} breakpoints. Only hit {breakcountHitCount}"); Assert.True(b.Uninstall(proj), "Project should have uninstalled."); session.Exit(); } }
public void CustomApplicationRunsWithDebuggerAndBreaks(bool useSharedRuntime, bool embedAssemblies, string fastDevType, bool activityStarts) { AssertCommercialBuild(); AssertHasDevices(); var proj = new XamarinAndroidApplicationProject() { IsRelease = false, AndroidFastDeploymentType = fastDevType, }; var abis = new string [] { "armeabi-v7a", "x86" }; proj.SetProperty(KnownProperties.AndroidSupportedAbis, string.Join(";", abis)); proj.SetProperty(KnownProperties.AndroidUseSharedRuntime, useSharedRuntime.ToString()); proj.SetProperty("EmbedAssembliesIntoApk", embedAssemblies.ToString()); proj.SetDefaultTargetDevice(); proj.Sources.Add(new BuildItem.Source("MyApplication.cs") { TextContent = () => proj.ProcessSourceTemplate(@"using System; using Android.App; using Android.OS; using Android.Runtime; using Android.Widget; namespace ${ROOT_NAMESPACE} { [Application] public class MyApplication : Application { public MyApplication (IntPtr handle, JniHandleOwnership jniHandle) : base (handle, jniHandle) { } public override void OnCreate () { base.OnCreate (); } } } "), }); using (var b = CreateApkBuilder(Path.Combine("temp", TestName))) { SetTargetFrameworkAndManifest(proj, b); Assert.True(b.Install(proj), "Project should have installed."); int breakcountHitCount = 0; ManualResetEvent resetEvent = new ManualResetEvent(false); var sw = new Stopwatch(); // setup the debugger var session = new SoftDebuggerSession(); session.Breakpoints = new BreakpointStore { { Path.Combine(Root, b.ProjectDirectory, "MainActivity.cs"), 19 }, { Path.Combine(Root, b.ProjectDirectory, "MyApplication.cs"), 17 }, }; session.TargetHitBreakpoint += (sender, e) => { TestContext.WriteLine($"BREAK {e.Type}, {e.Backtrace.GetFrame (0)}"); breakcountHitCount++; session.Continue(); }; var rnd = new Random(); int port = rnd.Next(10000, 20000); TestContext.Out.WriteLine($"{port}"); var args = new SoftDebuggerConnectArgs("", IPAddress.Loopback, port) { MaxConnectionAttempts = 10, }; var startInfo = new SoftDebuggerStartInfo(args) { WorkingDirectory = Path.Combine(b.ProjectDirectory, proj.IntermediateOutputPath, "android", "assets"), }; var options = new DebuggerSessionOptions() { EvaluationOptions = EvaluationOptions.DefaultOptions, }; options.EvaluationOptions.UseExternalTypeResolver = true; ClearAdbLogcat(); Assert.True(b.RunTarget(proj, "_Run", parameters: new string [] { $"AndroidSdbTargetPort={port}", $"AndroidSdbHostPort={port}", "AndroidAttachDebugger=True", }), "Project should have run."); // do we expect the app to start? Assert.AreEqual(activityStarts, WaitForDebuggerToStart(Path.Combine(Root, b.ProjectDirectory, "logcat.log")), "Activity should have started"); if (!activityStarts) { return; } // we need to give a bit of time for the debug server to start up. WaitFor(2000); session.LogWriter += (isStderr, text) => { Console.WriteLine(text); }; session.OutputWriter += (isStderr, text) => { Console.WriteLine(text); }; session.DebugWriter += (level, category, message) => { Console.WriteLine(message); }; session.Run(startInfo, options); var expectedTime = TimeSpan.FromSeconds(1); var actualTime = ProfileFor(() => session.IsConnected); TestContext.Out.WriteLine($"Debugger connected in {actualTime}"); Assert.LessOrEqual(actualTime, expectedTime, $"Debugger should have connected within {expectedTime} but it took {actualTime}."); // we need to wait here for a while to allow the breakpoints to hit // but we need to timeout TimeSpan timeout = TimeSpan.FromSeconds(60); while (session.IsConnected && breakcountHitCount < 2 && timeout >= TimeSpan.Zero) { Thread.Sleep(10); timeout = timeout.Subtract(TimeSpan.FromMilliseconds(10)); } WaitFor(2000); int expected = 2; Assert.AreEqual(expected, breakcountHitCount, $"Should have hit {expected} breakpoints. Only hit {breakcountHitCount}"); Assert.True(b.Uninstall(proj), "Project should have uninstalled."); session.Exit(); } }
private string SerializeDebuggerOptions(string jsonDebugOptions) { try { NLogService.TraceEnteringMethod(); var debugOptions = DebugOptions.DeserializeFromJson(jsonDebugOptions); _session = new SoftDebuggerSession(); _session.TargetReady += (sender, eventArgs) => { Debug.WriteLine("TargetReady!"); }; _session.ExceptionHandler = exception => true; _session.TargetExited += (sender, x) => { Debug.WriteLine("TargetExited!"); }; _session.TargetUnhandledException += (sender, x) => { Debug.WriteLine("TargetUnhandledException!"); }; _session.LogWriter = (stderr, text) => Debug.WriteLine(text); _session.OutputWriter = (stderr, text) => Debug.WriteLine(text); _session.TargetThreadStarted += (sender, x) => Debug.WriteLine("TargetThreadStarted!"); _session.TargetThreadStopped += (sender, x) => { Debug.WriteLine("TargetThreadStopped!"); }; _session.TargetStopped += (sender, x) => Debug.WriteLine(x.Type); _session.TargetStarted += (sender, x) => Debug.WriteLine("TargetStarted"); _session.TargetSignaled += (sender, x) => Debug.WriteLine(x.Type); _session.TargetInterrupted += (sender, x) => Debug.WriteLine(x.Type); _session.TargetExceptionThrown += (sender, x) => { Debug.WriteLine("TargetExceptionThrown!"); }; _session.TargetHitBreakpoint += (sender, x) => { Debug.WriteLine("TargetHitBreakpoint!"); }; _session.TargetEvent += _session_TargetEvent; var connectionTimeout = 30000; var evaluationTimeout = 30000; var startupProject = StartupProject; var softDebuggerConnectArgs = new SoftDebuggerConnectArgs(debugOptions.TargetExeFileName, debugOptions.GetHostIP(), debugOptions.GetMonoDebugPort()); // TODO implement programm output via stream //softDebuggerConnectArgs.RedirectOutput = true; //softDebuggerConnectArgs.OutputPort = ???; //_session.VirtualMachine.StandardOutput ??? softDebuggerConnectArgs.TimeBetweenConnectionAttempts = (int)debugOptions.UserSettings.TimeBetweenConnectionAttemptsInMs; softDebuggerConnectArgs.MaxConnectionAttempts = (int)debugOptions.UserSettings.MaxConnectionAttempts; _startInfo = new StartInfo( softDebuggerConnectArgs, new DebuggingOptions() { EvaluationTimeout = evaluationTimeout, MemberEvaluationTimeout = evaluationTimeout, ModificationTimeout = evaluationTimeout, SocketTimeout = connectionTimeout }, startupProject ); SessionMarshalling sessionMarshalling = new SessionMarshalling(_session, _startInfo); using (MemoryStream ms = new MemoryStream()) { BinaryFormatter bf = new BinaryFormatter(); ObjRef oref = RemotingServices.Marshal(sessionMarshalling); bf.Serialize(ms, oref); return(Convert.ToBase64String(ms.ToArray())); } } catch (Exception ex) { NLogService.Logger.Error(ex); throw; } }
public int LaunchSuspended(string server, IDebugPort2 port, string exe, string args, string directory, string environment, string options, enum_LAUNCH_FLAGS launchFlags, uint standardInput, uint standardOutput, uint standardError, IDebugEventCallback2 callback, out IDebugProcess2 process) { waiter = new AutoResetEvent(false); settings = MonoDebuggerSettings.Parse(options); Task.Run(() => { var outputWindow = (IVsOutputWindow)Microsoft.VisualStudio.Shell.Package.GetGlobalService(typeof(SVsOutputWindow)); var generalPaneGuid = VSConstants.GUID_OutWindowDebugPane; outputWindow.GetPane(ref generalPaneGuid, out this.outputWindow); // Upload the contents of the output folder to the target directory if (connection == null) { connection = ConnectionManager.Get(settings); if (!connection.IsConnected) { Log("Connecting SSH and SFTP..."); // Debugger.Launch(); connection.Connect(); Log("Connected"); } } Log("Uploading program..."); // Ensure target directory exists: var targetDirectories = directory.Split('/'); foreach (var part in targetDirectories) { if (!connection.Sftp.Exists(part)) { connection.Sftp.CreateDirectory(part); } connection.Sftp.ChangeDirectory(part); } foreach (var _ in targetDirectories) { connection.Sftp.ChangeDirectory(".."); } var outputDirectory = new DirectoryInfo(Path.GetDirectoryName(exe)); foreach (var file in outputDirectory.EnumerateFiles().Where(x => x.Extension == ".dll" || x.Extension == ".mdb" || x.Extension == ".exe")) { using (var stream = file.OpenRead()) { connection.Sftp.UploadFile(stream, $"{directory}/{file.Name}", true); } Log($"Uploaded {file.FullName}"); } Log("Done"); var targetExe = directory + "/" + Path.GetFileName(exe); connection.Ssh.RunCommand("cd ~"); Log("Launching application"); var commandText = $"mono --debug=mdb-optimizations --debugger-agent=transport=dt_socket,address=0.0.0.0:6438,server=y {targetExe}"; connection.Ssh.RunCommand("kill $(ps auxww | grep '" + commandText + "' | awk '{print $2}')", this.outputWindow, null); runCommand = connection.Ssh.BeginCommand(commandText, this.outputWindow, out runCommandAsyncResult); // Trigger that the app is now running for whomever might be waiting for that signal waiter.Set(); }); Session = new SoftDebuggerSession(); Session.TargetReady += (sender, eventArgs) => { var activeThread = Session.ActiveThread; ThreadManager.Add(activeThread, new MonoThread(this, activeThread)); // Session.Stop(); }; Session.ExceptionHandler = exception => true; Session.TargetExited += (sender, x) => { // runCommand.EndExecute(runCommandAsyncResult); Send(new MonoProgramDestroyEvent((uint?)x.ExitCode ?? 0), MonoProgramDestroyEvent.IID, null); }; Session.TargetUnhandledException += (sender, x) => { Send(new MonoExceptionEvent(x.Backtrace.GetFrame(0)) { IsUnhandled = true }, MonoExceptionEvent.IID, ThreadManager[x.Thread]); }; Session.LogWriter = (stderr, text) => Console.WriteLine(text); Session.OutputWriter = (stderr, text) => Console.WriteLine(text); Session.TargetThreadStarted += (sender, x) => ThreadManager.Add(x.Thread, new MonoThread(this, x.Thread)); Session.TargetThreadStopped += (sender, x) => { ThreadManager.Remove(x.Thread); }; Session.TargetStopped += (sender, x) => Console.WriteLine(x.Type); Session.TargetStarted += (sender, x) => Console.WriteLine(); Session.TargetSignaled += (sender, x) => Console.WriteLine(x.Type); Session.TargetInterrupted += (sender, x) => Console.WriteLine(x.Type); Session.TargetExceptionThrown += (sender, x) => { Send(new MonoExceptionEvent(x.Backtrace.GetFrame(0)), MonoExceptionEvent.IID, ThreadManager[x.Thread]); }; Session.TargetHitBreakpoint += (sender, x) => { var breakpoint = x.BreakEvent as Breakpoint; var pendingBreakpoint = breakpointManager[breakpoint]; Send(new MonoBreakpointEvent(new MonoBoundBreakpointsEnum(pendingBreakpoint.BoundBreakpoints)), MonoBreakpointEvent.IID, ThreadManager[x.Thread]); }; processId = new AD_PROCESS_ID(); processId.ProcessIdType = (uint)enum_AD_PROCESS_ID.AD_PROCESS_ID_GUID; processId.guidProcessId = Guid.NewGuid(); EngineUtils.CheckOk(port.GetProcess(processId, out process)); Callback = callback; return(VSConstants.S_OK); }
public void DotNetDebug() { AssertCommercialBuild(); AssertHasDevices(); XASdkProject proj; proj = new XASdkProject { //TODO: targetSdkVersion="30" causes a crash on startup in .NET 5 MinSdkVersion = null, TargetSdkVersion = null, }; proj.SetRuntimeIdentifier(DeviceAbi); var relativeProjDir = Path.Combine("temp", TestName); var fullProjDir = Path.Combine(Root, relativeProjDir); TestOutputDirectories [TestContext.CurrentContext.Test.ID] = fullProjDir; var files = proj.Save(); proj.Populate(relativeProjDir, files); proj.CopyNuGetConfig(relativeProjDir); var dotnet = new DotNetCLI(proj, Path.Combine(fullProjDir, proj.ProjectFilePath)); Assert.IsTrue(dotnet.Build("Install"), "`dotnet build` should succeed"); bool breakpointHit = false; ManualResetEvent resetEvent = new ManualResetEvent(false); var sw = new Stopwatch(); // setup the debugger var session = new SoftDebuggerSession(); session.Breakpoints = new BreakpointStore { { Path.Combine(Root, dotnet.ProjectDirectory, "MainActivity.cs"), 19 }, }; session.TargetHitBreakpoint += (sender, e) => { Console.WriteLine($"BREAK {e.Type}"); breakpointHit = true; session.Continue(); }; var rnd = new Random(); int port = rnd.Next(10000, 20000); TestContext.Out.WriteLine($"{port}"); var args = new SoftDebuggerConnectArgs("", IPAddress.Loopback, port) { MaxConnectionAttempts = 10, }; var startInfo = new SoftDebuggerStartInfo(args) { WorkingDirectory = Path.Combine(dotnet.ProjectDirectory, proj.IntermediateOutputPath, "android", "assets"), }; var options = new DebuggerSessionOptions() { EvaluationOptions = EvaluationOptions.DefaultOptions, }; options.EvaluationOptions.UseExternalTypeResolver = true; ClearAdbLogcat(); Assert.True(dotnet.Build("Run", new string [] { $"AndroidSdbTargetPort={port}", $"AndroidSdbHostPort={port}", "AndroidAttachDebugger=True", }), "Project should have run."); Assert.IsTrue(WaitForDebuggerToStart(Path.Combine(Root, dotnet.ProjectDirectory, "logcat.log")), "Activity should have started"); // we need to give a bit of time for the debug server to start up. WaitFor(2000); session.LogWriter += (isStderr, text) => { Console.WriteLine(text); }; session.OutputWriter += (isStderr, text) => { Console.WriteLine(text); }; session.DebugWriter += (level, category, message) => { Console.WriteLine(message); }; session.Run(startInfo, options); WaitFor(TimeSpan.FromSeconds(30), () => session.IsConnected); Assert.True(session.IsConnected, "Debugger should have connected but it did not."); // we need to wait here for a while to allow the breakpoints to hit // but we need to timeout TimeSpan timeout = TimeSpan.FromSeconds(60); while (session.IsConnected && !breakpointHit && timeout >= TimeSpan.Zero) { Thread.Sleep(10); timeout = timeout.Subtract(TimeSpan.FromMilliseconds(10)); } WaitFor(2000); Assert.IsTrue(breakpointHit, "Should have a breakpoint"); }