// Called by the SDM to indicate that a synchronous debug event, previously sent by the DE to the SDM, // was received and processed. The only event the sample engine sends in this fashion is Program Destroy. // It responds to that event by shutting down the engine. int IDebugEngine2.ContinueFromSynchronousEvent(IDebugEvent2 eventObject) { // Debug.Assert(Worker.MainThreadId == Worker.CurrentThreadId); try { if (eventObject is AD7ProgramDestroyEvent) { //WorkerThread pollThread = m_pollThread; SquirrelProcess _debuggedProcess = debuggedProcess; m_engineCallback = null; debuggedProcess = null; //m_pollThread = null; m_ad7ProgramId = Guid.Empty; _debuggedProcess.Close(); //pollThread.Close(); } else if (eventObject is ErrorEvent) { ErrorEvent errorEventObject = eventObject as ErrorEvent; if (errorEventObject != null) { Debug.WriteLine("Debugger received errorevent " + errorEventObject.ErrorMessage + "\n"); } return(EngineConstants.E_FAIL); // m_engineCallback.Send(new AD7ProgramDestroyEvent(0), AD7ProgramDestroyEvent.IID, null); } else { Debug.Fail("Debug engine received unknown synchronous event"); } } catch (Exception e) { return(EngineUtils.UnexpectedException(e)); } return(EngineConstants.S_OK); }
// Launches a process by means of the debug engine. // Normally, Visual Studio launches a program using the IDebugPortEx2::LaunchSuspended method and then attaches the debugger // to the suspended program. However, there are circumstances in which the debug engine may need to launch a program // (for example, if the debug engine is part of an interpreter and the program being debugged is an interpreted language), // in which case Visual Studio uses the IDebugEngineLaunch2::LaunchSuspended method // The IDebugEngineLaunch2::ResumeProcess method is called to start the process after the process has been successfully launched in a suspended state. int IDebugEngineLaunch2.LaunchSuspended(string pszServer, IDebugPort2 port, string exe, string args, string dir, string env, string options, enum_LAUNCH_FLAGS launchFlags, uint hStdInput, uint hStdOutput, uint hStdError, IDebugEventCallback2 ad7Callback, out IDebugProcess2 process) { //Debug.Assert(Worker.MainThreadId == Worker.CurrentThreadId); //Debug.Assert(m_pollThread == null); Debug.Assert(m_engineCallback == null); Debug.Assert(debuggedProcess == null); Debug.Assert(m_ad7ProgramId == Guid.Empty); process = null; try { //string commandLine = EngineUtils.BuildCommandLine(exe, args); //ProcessLaunchInfo processLaunchInfo = new ProcessLaunchInfo(exe, commandLine, dir, env, options, (uint)launchFlags, hStdInput, hStdOutput, hStdError); // We are being asked to debug a process when we currently aren't debugging anything //m_pollThread = new WorkerThread(); string portname; port.GetPortName(out portname); m_engineCallback = new EngineCallback(this, ad7Callback); XmlDocument doc = new XmlDocument(); doc.LoadXml(options); XmlElement root = (XmlElement)doc.ChildNodes[0]; string ipaddress = root.GetAttribute("targetaddress"); int ipport = Int32.Parse(root.GetAttribute("port")); int connectiontries = Int32.Parse(root.GetAttribute("connectiontries")); int connectiondelay = Int32.Parse(root.GetAttribute("connectiondelay")); bool autoruninterpreter = Boolean.Parse(root.GetAttribute("autoruninterpreter")); bool suspendonstartup = Boolean.Parse(root.GetAttribute("suspendonstartup")); List <SquirrelDebugFileContext> ctxs = new List <SquirrelDebugFileContext>(); foreach (XmlElement e in doc.GetElementsByTagName("context")) { string rootpath = e.GetAttribute("rootpath"); string pathfixup = e.GetAttribute("pathfixup"); SquirrelDebugFileContext sdfc = new SquirrelDebugFileContext(rootpath, pathfixup); ctxs.Add(sdfc); } // Complete the win32 attach on the poll thread //THIS IS A MASSIVE HACK //the 'options' parameter is formatted this way "targetaddress,port,autorunintepreter,suspendonstartup,projectfolder,pathfixup" //I should find a better way to pass this params //fix working dir) dir = dir.Replace('/', '\\'); Process proc = null; if (autoruninterpreter) { proc = new Process(); proc.EnableRaisingEvents = false; proc.StartInfo.UseShellExecute = false; baseDir = proc.StartInfo.WorkingDirectory = dir; proc.StartInfo.FileName = exe; proc.StartInfo.Arguments = args; proc.StartInfo.RedirectStandardOutput = false; proc.StartInfo.RedirectStandardError = false; proc.Start(); } AD_PROCESS_ID adProcessId = new AD_PROCESS_ID(); if (proc != null) { adProcessId.ProcessIdType = (uint)enum_AD_PROCESS_ID.AD_PROCESS_ID_SYSTEM; adProcessId.dwProcessId = (uint)proc.Id; } else { adProcessId.ProcessIdType = (uint)enum_AD_PROCESS_ID.AD_PROCESS_ID_GUID; adProcessId.guidProcessId = Guid.NewGuid(); } EngineUtils.RequireOk(port.GetProcess(adProcessId, out process)); debuggedProcess = (SquirrelProcess)process; debuggedProcess.Engine = this; debuggedProcess.Process = proc; debuggedProcess.Name = proc != null? proc.StartInfo.FileName : "remoteprocess"; debuggedProcess.EngineCallback = m_engineCallback; debuggedProcess.IpAddress = ipaddress; debuggedProcess.IpPort = ipport; debuggedProcess.SuspendOnStartup = suspendonstartup; debuggedProcess.FileContexts = ctxs.ToArray(); //debuggedProcess.ConnectionTries = connectiontries; //debuggedProcess.ConnectionDelay = connectiondelay; //debuggedProcess.PathFixup = pathfixup; //debuggedProcess.ProjectFolder = projectfolder; /*DebuggedThread thread = new DebuggedThread(1); * DebuggedModule module = new DebuggedModule("the module"); * * m_engineCallback.OnModuleLoad(module); * m_engineCallback.OnSymbolSearch(module, "nothing", 0); * m_engineCallback.OnThreadStart(thread); * m_engineCallback.OnLoadComplete(thread);*/ return(EngineConstants.S_OK); } catch (ComponentException e) { return(e.HRESULT); } catch (Exception e) { return(EngineUtils.UnexpectedException(e)); } }