예제 #1
0
        public static int GetProcessId(IDebugProcess2 process)
        {
            AD_PROCESS_ID[] pid = new AD_PROCESS_ID[1];
            EngineUtils.RequireOk(process.GetPhysicalProcessId(pid));

            if (pid[0].ProcessIdType != (uint)enum_AD_PROCESS_ID.AD_PROCESS_ID_SYSTEM)
            {
                return(0);
            }

            return((int)pid[0].dwProcessId);
        }
예제 #2
0
        internal void Send(IDebugEvent2 eventObject, string iidEvent, IDebugProgram2 program, IDebugThread2 thread)
        {
            uint attributes;
            Guid riidEvent = new Guid(iidEvent);

            EngineUtils.RequireOk(eventObject.GetAttributes(out attributes));

            Debug.WriteLine(String.Format("Sending Event: {0} {1}", eventObject.GetType(), iidEvent));
            try {
                EngineUtils.RequireOk(_events.Event(this, null, program, thread, eventObject, ref riidEvent, attributes));
            } catch (InvalidCastException) {
                // COM object has gone away
            }
        }
예제 #3
0
        // 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.WriteLine("PythonEngine LaunchSuspended Begin " + launchFlags + " " + GetHashCode());
            AssertMainThread();
            Debug.Assert(_events == null);
            Debug.Assert(_process == null);
            Debug.Assert(_ad7ProgramId == Guid.Empty);

            process = null;

            _events = ad7Callback;

            PythonLanguageVersion version      = DefaultVersion;
            bool            waitOnAbnormalExit = false;
            bool            redirectOutput     = false;
            List <string[]> dirMapping         = null;

            if (options != null)
            {
                var splitOptions = options.Split(new[] { ';' }, 2);
                foreach (var optionSetting in splitOptions)
                {
                    var setting = optionSetting.Split(new[] { '=' }, 2);

                    if (setting.Length == 2)
                    {
                        switch (setting[0])
                        {
                        case VersionSetting: version = GetLanguageVersion(setting[1]); break;

                        case WaitOnAbnormalExitSetting:
                            bool value;
                            if (Boolean.TryParse(setting[1], out value))
                            {
                                waitOnAbnormalExit = value;
                            }
                            break;

                        case RedirectOutputSetting:
                            if (Boolean.TryParse(setting[1], out value))
                            {
                                redirectOutput = value;
                            }
                            break;

                        case DirMappingSetting:
                            string[] dirs = setting[1].Split('|');
                            if (dirs.Length == 2)
                            {
                                if (dirMapping == null)
                                {
                                    dirMapping = new List <string[]>();
                                }
                                Debug.WriteLine(String.Format("Mapping dir {0} to {1}", dirs[0], dirs[1]));
                                dirMapping.Add(dirs);
                            }
                            break;
                        }
                    }
                }
            }

            _process = new PythonProcess(version, exe, args, dir, env, waitOnAbnormalExit, redirectOutput, dirMapping);

            AttachEvents(_process);

            _programCreated = false;
            _loadComplete.Reset();

            _process.Start();

            AD_PROCESS_ID adProcessId = new AD_PROCESS_ID();

            adProcessId.ProcessIdType = (uint)enum_AD_PROCESS_ID.AD_PROCESS_ID_SYSTEM;
            adProcessId.dwProcessId   = (uint)_process.Id;

            EngineUtils.RequireOk(port.GetProcess(adProcessId, out process));
            Debug.WriteLine("PythonEngine LaunchSuspended returning S_OK");
            Debug.Assert(process != null);
            Debug.Assert(!_process.HasExited);

            return(VSConstants.S_OK);
        }
예제 #4
0
        // Resume a process launched by IDebugEngineLaunch2.LaunchSuspended
        int IDebugEngineLaunch2.ResumeProcess(IDebugProcess2 process)
        {
            Debug.WriteLine("Python Debugger ResumeProcess Begin");

            AssertMainThread();
            if (_events == null)
            {
                // process failed to start
                Debug.WriteLine("ResumeProcess fails, no events");
                return(VSConstants.E_FAIL);
            }

            Debug.Assert(_events != null);
            Debug.Assert(_process != null);
            Debug.Assert(_process != null);
            Debug.Assert(_ad7ProgramId == Guid.Empty);

            int processId = EngineUtils.GetProcessId(process);

            if (processId != _process.Id)
            {
                Debug.WriteLine("ResumeProcess fails, wrong process");
                return(VSConstants.S_FALSE);
            }

            // Send a program node to the SDM. This will cause the SDM to turn around and call IDebugEngine2.Attach
            // which will complete the hookup with AD7
            IDebugPort2 port;

            EngineUtils.RequireOk(process.GetPort(out port));

            IDebugDefaultPort2 defaultPort = (IDebugDefaultPort2)port;

            IDebugPortNotify2 portNotify;

            EngineUtils.RequireOk(defaultPort.GetPortNotify(out portNotify));

            EngineUtils.RequireOk(portNotify.AddProgramNode(new AD7ProgramNode(_process.Id)));

            if (_ad7ProgramId == Guid.Empty)
            {
                Debug.WriteLine("ResumeProcess fails, empty program guid");
                Debug.Fail("Unexpected problem -- IDebugEngine2.Attach wasn't called");
                return(VSConstants.E_FAIL);
            }

            // wait for the load event to complete, and pump messages

            while (!_process.HasExited && !_loadComplete.WaitOne(100))
            {
                Debug.WriteLine("ResumeProcess waiting for load complete");
            }

            // Resume the threads in the debuggee process
            if (_process.HasExited)
            {
                Debug.WriteLine("ResumeProcess resume all");
                _process.Resume();
            }
            else
            {
                // return failure?
                Debug.WriteLine("Process exited");
            }

            Debug.WriteLine("ResumeProcess return S_OK");
            return(VSConstants.S_OK);
        }
예제 #5
0
        // Attach the debug engine to a program.
        int IDebugEngine2.Attach(IDebugProgram2[] rgpPrograms, IDebugProgramNode2[] rgpProgramNodes, uint celtPrograms, IDebugEventCallback2 ad7Callback, enum_ATTACH_REASON dwReason)
        {
            Debug.WriteLine("PythonEngine Attach Begin " + GetHashCode());

            AssertMainThread();
            Debug.Assert(_ad7ProgramId == Guid.Empty);

            if (celtPrograms != 1)
            {
                Debug.Fail("Python debugging only supports one program in a process");
                throw new ArgumentException();
            }

            int processId = EngineUtils.GetProcessId(rgpPrograms[0]);

            if (processId == 0)
            {
                // engine only supports system processes
                Debug.WriteLine("PythonEngine failed to get process id during attach");
                return(VSConstants.E_NOTIMPL);
            }

            EngineUtils.RequireOk(rgpPrograms[0].GetProgramId(out _ad7ProgramId));

            // Attach can either be called to attach to a new process, or to complete an attach
            // to a launched process
            if (_process == null)
            {
                // TODO: Where do we get the language version from?
                _events = ad7Callback;

                var attachRes = PythonProcess.TryAttach(processId, out _process);
                if (attachRes != ConnErrorMessages.None)
                {
                    string msg;
                    switch (attachRes)
                    {
                    case ConnErrorMessages.CannotInjectThread: msg = "Cannot create thread in debuggee process"; break;

                    case ConnErrorMessages.CannotOpenProcess: msg = "Cannot open process for debugging"; break;

                    case ConnErrorMessages.InterpreterNotInitialized: msg = "Python interpreter has not been initialized in this process"; break;

                    case ConnErrorMessages.LoadDebuggerBadDebugger: msg = "Failed to load debugging script (incorrect version of script?)"; break;

                    case ConnErrorMessages.LoadDebuggerFailed: msg = "Failed to compile debugging script"; break;

                    case ConnErrorMessages.OutOfMemory: msg = "Out of memory"; break;

                    case ConnErrorMessages.PythonNotFound: msg = "Python interpreter not found"; break;

                    case ConnErrorMessages.TimeOut: msg = "Timeout while attaching"; break;

                    case ConnErrorMessages.UnknownVersion: msg = "Unknown Python version loaded in process"; break;

                    case ConnErrorMessages.SysNotFound: msg = "sys module not found"; break;

                    case ConnErrorMessages.SysSetTraceNotFound: msg = "settrace not found in sys module"; break;

                    case ConnErrorMessages.PyDebugAttachNotFound: msg = "Cannot find PyDebugAttach.dll at " + attachRes; break;

                    default: msg = "Unknown error"; break;
                    }

                    MessageBox.Show("Failed to attach debugger: " + msg);
                    return(VSConstants.E_FAIL);
                }

                AttachEvents(_process);
                _attached = true;
            }
            else
            {
                if (processId != _process.Id)
                {
                    Debug.Fail("Asked to attach to a process while we are debugging");
                    return(VSConstants.E_FAIL);
                }
                _attached = false;
            }

            AD7EngineCreateEvent.Send(this);

            lock (_syncLock) {
                _programCreated = true;
                AD7ProgramCreateEvent.Send(this);

                if (_processLoadedThread != null)
                {
                    SendLoadComplete(_processLoadedThread);
                }
            }

            Debug.WriteLine("PythonEngine Attach returning S_OK");
            return(VSConstants.S_OK);
        }