コード例 #1
0
ファイル: PythonProcess.cs プロジェクト: KevinH-MS/PTVS
        private PythonProcess(int pid, PythonDebugOptions debugOptions) {
            _pid = pid;
            _process = Process.GetProcessById(pid);
            _process.EnableRaisingEvents = true;
            _process.Exited += new EventHandler(_process_Exited);

            ListenForConnection();

            using (var result = DebugAttach.AttachAD7(pid, DebugConnectionListener.ListenerPort, _processGuid, debugOptions.ToString())) {
                if (result.Error != ConnErrorMessages.None) {
                    throw new ConnectionException(result.Error);
                }

                _langVersion = (PythonLanguageVersion)result.LanguageVersion;
                if (!result.AttachDone.WaitOne(20000)) {
                    throw new ConnectionException(ConnErrorMessages.TimeOut);
                }
            }
        }
コード例 #2
0
ファイル: DebugExtensions.cs プロジェクト: wenh123/PTVS
        internal static PythonProcess DebugProcess(this PythonDebugger debugger, PythonVersion version, string filename, Action<PythonProcess, PythonThread> onLoaded = null, bool resumeOnProcessLoaded = true, string interpreterOptions = null, PythonDebugOptions debugOptions = PythonDebugOptions.RedirectOutput, string cwd = null, string arguments = "") {
            string fullPath = Path.GetFullPath(filename);
            string dir = cwd ?? Path.GetFullPath(Path.GetDirectoryName(filename));
            if (!String.IsNullOrEmpty(arguments)) {
                arguments = "\"" + fullPath + "\" " + arguments;
            } else {
                arguments = "\"" + fullPath + "\"";
            }
            var process = debugger.CreateProcess(version.Version, version.InterpreterPath, arguments, dir, "", interpreterOptions, debugOptions);
            process.DebuggerOutput += (sender, args) => {
                Console.WriteLine("{0}: {1}", args.Thread.Id, args.Output);
            };
            process.ProcessLoaded += (sender, args) => {
                if (onLoaded != null) {
                    onLoaded(process, args.Thread);
                }
                if (resumeOnProcessLoaded) {
                    process.Resume();
                }
            };

            return process;
        }
コード例 #3
0
        // TODO: turn PythonDebugOptions into a class that encapsulates all options (not just flags), including the "not set"
        // state for all of them, and that knows how to stringify and parse itself, and how to merge isntances, and refactor
        // this entire codepath, including the bits in DefaultPythonLauncher and in CustomDebuggerEventHandler, to use that.
        private void ParseOptions(string options)
        {
            foreach (var optionSetting in SplitOptions(options)) {
                var setting = optionSetting.Split(new[] { '=' }, 2);
                if (setting.Length == 2) {
                    switch (setting[0]) {
                        case VersionSetting:
                            _languageVersion = GetLanguageVersion(setting[1]);
                            break;

                        case WaitOnAbnormalExitSetting:
                            bool value;
                            if (Boolean.TryParse(setting[1], out value) && value) {
                                _debugOptions |= PythonDebugOptions.WaitOnAbnormalExit;
                            }
                            break;

                        case WaitOnNormalExitSetting:
                            if (Boolean.TryParse(setting[1], out value) && value) {
                                _debugOptions |= PythonDebugOptions.WaitOnNormalExit;
                            }
                            break;

                        case RedirectOutputSetting:
                            if (Boolean.TryParse(setting[1], out value) && value) {
                                _debugOptions |= PythonDebugOptions.RedirectOutput;
                            }
                            break;

                        case BreakSystemExitZero:
                            if (Boolean.TryParse(setting[1], out value) && value) {
                                _debugOptions |= PythonDebugOptions.BreakOnSystemExitZero;
                            }
                            break;

                        case DebugStdLib:
                            if (Boolean.TryParse(setting[1], out value) && value) {
                                _debugOptions |= PythonDebugOptions.DebugStdLib;
                            }
                            break;

                        case IsWindowsApplication:
                            if (Boolean.TryParse(setting[1], out value) && value) {
                                _debugOptions |= PythonDebugOptions.IsWindowsApplication;
                            }
                            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;

                        case InterpreterOptions:
                            _interpreterOptions = setting[1];
                            break;

                        case AttachRunning:
                            if (Boolean.TryParse(setting[1], out value) && value) {
                                _debugOptions |= PythonDebugOptions.AttachRunning;
                            }
                            break;

                        case WebBrowserUrl:
                            _webBrowserUrl = HttpUtility.UrlDecode(setting[1]);
                            break;

                        case EnableDjangoDebugging:
                            if (Boolean.TryParse(setting[1], out value) && value) {
                                _debugOptions |= PythonDebugOptions.DjangoDebugging;
                            }
                            break;
                    }
                }
            }
        }
コード例 #4
0
ファイル: DebuggerTests.cs プロジェクト: KaushikCh/PTVS
        private new PythonProcess DebugProcess(PythonDebugger debugger, string filename, Action<PythonProcess, PythonThread> onLoaded = null, bool resumeOnProcessLoaded = true, string interpreterOptions = null, PythonDebugOptions debugOptions = PythonDebugOptions.RedirectOutput, string cwd = null, string pythonExe = null) {
            string fullPath = Path.GetFullPath(filename);
            string dir = cwd ?? Path.GetFullPath(Path.GetDirectoryName(filename));
            var process = debugger.CreateProcess(Version.Version, pythonExe ?? Version.InterpreterPath, "\"" + fullPath + "\"", dir, "", interpreterOptions, debugOptions);
            process.ProcessLoaded += (sender, args) => {
                if (onLoaded != null) {
                    onLoaded(process, args.Thread);
                }
                if (resumeOnProcessLoaded) {
                    process.Resume();
                }
            };

            return process;
        }
コード例 #5
0
ファイル: DebuggerTests.cs プロジェクト: KaushikCh/PTVS
        private void TestException(
            PythonDebugger debugger,
            string filename,
            bool resumeProcess,
            ExceptionMode defaultExceptionMode,
            ICollection<KeyValuePair<string, ExceptionMode>> exceptionModes,
            PythonDebugOptions debugOptions,
            params ExceptionInfo[] exceptions
        ) {
            Console.WriteLine();
            Console.WriteLine("Testing {0}", filename);

            bool loaded = false;
            var process = DebugProcess(debugger, filename, (processObj, threadObj) => {
                loaded = true;
                processObj.SetExceptionInfo(
                    (int)defaultExceptionMode,
                    exceptionModes == null ?
                        Enumerable.Empty<KeyValuePair<string, int>>() :
                        exceptionModes.Select(m => new KeyValuePair<string, int>(m.Key, (int)m.Value))
                );
            }, debugOptions: debugOptions);

            var raised = new List<Tuple<string, string>>();
            process.ExceptionRaised += (sender, args) => {
                if (loaded) {
                    raised.Add(Tuple.Create(args.Exception.TypeName, TryGetStack(args.Thread)));
                }
                if (resumeProcess) {
                    process.Resume();
                } else {
                    args.Thread.Resume();
                }
            };

            StartAndWaitForExit(process);

            if (Version.Version == PythonLanguageVersion.V30 && raised.Count > exceptions.Length) {
                // Python 3.0 raises an exception as the process shuts down.
                raised.RemoveAt(raised.Count - 1);
            }

            if (GetType() == typeof(DebuggerTestsIpy) && raised.Count == exceptions.Length + 1) {
                // IronPython over-reports exceptions
                raised.RemoveAt(raised.Count - 1);
            }

            foreach (var t in raised) {
                Console.WriteLine("Received {0} at{1}{2}", t.Item1, Environment.NewLine, t.Item2);
            }
            AssertUtil.AreEqual(
                raised.Select(t => t.Item1),
                exceptions.Select(e => e.TypeName).ToArray()
            );
        }
コード例 #6
0
ファイル: PythonProcess.cs プロジェクト: KevinH-MS/PTVS
        private PythonProcess(Stream stream, int pid, PythonLanguageVersion version, PythonDebugOptions debugOptions) {
            _pid = pid;
            _process = Process.GetProcessById(pid);
            _process.EnableRaisingEvents = true;
            _process.Exited += new EventHandler(_process_Exited);
            
            _delayUnregister = true;
            
            ListenForConnection();

            stream.WriteInt32(DebugConnectionListener.ListenerPort);
            stream.WriteString(_processGuid.ToString());
            stream.WriteString(debugOptions.ToString());
        }
コード例 #7
0
ファイル: PythonProcess.cs プロジェクト: KevinH-MS/PTVS
 public static PythonProcess AttachRepl(Stream stream, int pid, PythonLanguageVersion version, PythonDebugOptions debugOptions = PythonDebugOptions.None) {
     return new PythonProcess(stream, pid, version, debugOptions);
 }
コード例 #8
0
 /// <summary>
 /// Creates a new PythonProcess object for debugging.  The process does not start until Start is called
 /// on the returned PythonProcess object.
 /// </summary>
 public PythonProcess CreateProcess(PythonLanguageVersion langVersion, string exe, string args, string dir, string env, string interpreterOptions = null, PythonDebugOptions debugOptions = PythonDebugOptions.None, TextWriter debugLog = null)
 {
     return(new PythonProcess(langVersion, exe, args, dir, env, interpreterOptions, debugOptions, debugLog));
 }
コード例 #9
0
ファイル: PythonProcess.cs プロジェクト: KevinH-MS/PTVS
        public PythonProcess(PythonLanguageVersion languageVersion, string exe, string args, string dir, string env, string interpreterOptions, PythonDebugOptions options = PythonDebugOptions.None, List<string[]> dirMapping = null)
            : this(0, languageVersion) {

            ListenForConnection();

            if (dir.EndsWith("\\")) {
                dir = dir.Substring(0, dir.Length - 1);
            }
            _dirMapping = dirMapping;
            var processInfo = new ProcessStartInfo(exe);

            processInfo.CreateNoWindow = (options & PythonDebugOptions.CreateNoWindow) != 0;
            processInfo.UseShellExecute = false;
            processInfo.RedirectStandardOutput = false;
            processInfo.RedirectStandardInput = (options & PythonDebugOptions.RedirectInput) != 0;

            processInfo.Arguments = 
                (String.IsNullOrWhiteSpace(interpreterOptions) ? "" : (interpreterOptions + " ")) +
                "\"" + PythonToolsInstallPath.GetFile("visualstudio_py_launcher.py") + "\" " +
                "\"" + dir + "\" " +
                " " + DebugConnectionListener.ListenerPort + " " +
                " " + _processGuid + " " +
                "\"" + options + "\" " +
                args;

            if (env != null) {
                string[] envValues = env.Split('\0');
                foreach (var curValue in envValues) {
                    string[] nameValue = curValue.Split(new[] { '=' }, 2);
                    if (nameValue.Length == 2 && !String.IsNullOrWhiteSpace(nameValue[0])) {
                        processInfo.EnvironmentVariables[nameValue[0]] = nameValue[1];
                    }
                }
            }

            Debug.WriteLine(String.Format("Launching: {0} {1}", processInfo.FileName, processInfo.Arguments));
            _process = new Process();
            _process.StartInfo = processInfo;
            _process.EnableRaisingEvents = true;
            _process.Exited += new EventHandler(_process_Exited);
        }
コード例 #10
0
        internal async Task StepTestAsync(string filename, string breakFile, string arguments, int[] breakLines, Action <PythonProcess>[] breakAction, Action processLoaded, PythonDebugOptions options = PythonDebugOptions.RedirectOutput, bool waitForExit = true, params ExpectedStep[] kinds)
        {
            Console.WriteLine("--- Begin Step Test ---");
            var debugger = new PythonDebugger();

            if (breakFile == null)
            {
                breakFile = filename;
            }

            string fullPath = Path.GetFullPath(filename);
            string dir      = Path.GetDirectoryName(filename);
            var    process  = debugger.CreateProcess(Version.Version, Version.InterpreterPath, "\"" + fullPath + "\" " + (arguments ?? ""), dir, "", null, options, DebugLog);

            try {
                PythonThread thread = null;
                process.ThreadCreated += (sender, args) => {
                    thread = args.Thread;
                };


                AutoResetEvent processEvent = new AutoResetEvent(false);

                bool processLoad = false, stepComplete = false;
                process.ProcessLoaded += async(sender, args) => {
                    foreach (var breakLine in breakLines)
                    {
                        var bp = process.AddBreakpointByFileExtension(breakLine, breakFile);
                        await bp.AddAsync(TimeoutToken());
                    }

                    processLoad = true;
                    processEvent.Set();
                    processLoaded?.Invoke();
                };

                process.StepComplete += (sender, args) => {
                    stepComplete = true;
                    processEvent.Set();
                };

                int breakHits             = 0;
                ExceptionDispatchInfo edi = null;
                process.BreakpointHit += (sender, args) => {
                    try {
                        Console.WriteLine("Breakpoint hit");
                        if (breakAction != null)
                        {
                            if (breakHits >= breakAction.Length)
                            {
                                Assert.Fail("Unexpected breakpoint hit at {0}:{1}", args.Breakpoint.Filename, args.Breakpoint.LineNo);
                            }
                            breakAction[breakHits++](process);
                        }
                        stepComplete = true;
                        processEvent.Set();
                    } catch (Exception ex) {
                        edi = ExceptionDispatchInfo.Capture(ex);
                        try {
                            processEvent.Set();
                        } catch { }
                    }
                };

                await process.StartAsync();

                for (int curStep = 0; curStep < kinds.Length; curStep++)
                {
                    Console.WriteLine("Step {0} {1}", curStep, kinds[curStep].Kind);
                    // process the stepping events as they occur, we cannot callback during the
                    // event because the notificaiton happens on the debugger thread and we
                    // need to callback to get the frames.
                    AssertWaited(processEvent);
                    edi?.Throw();

                    // first time through we hit process load, each additional time we should hit step complete.
                    Debug.Assert((processLoad == true && stepComplete == false && curStep == 0) ||
                                 (stepComplete == true && processLoad == false && curStep != 0));

                    processLoad = stepComplete = false;

                    var frames   = thread.Frames;
                    var stepInfo = kinds[curStep];
                    Assert.AreEqual(stepInfo.StartLine, frames[0].LineNo, String.Format("{0} != {1} on {2} step", stepInfo.StartLine, frames[0].LineNo, curStep));

                    switch (stepInfo.Kind)
                    {
                    case StepKind.Into:
                        await thread.StepIntoAsync(TimeoutToken());

                        break;

                    case StepKind.Out:
                        await thread.StepOutAsync(TimeoutToken());

                        break;

                    case StepKind.Over:
                        await thread.StepOverAsync(TimeoutToken());

                        break;

                    case StepKind.Resume:
                        await process.ResumeAsync(TimeoutToken());

                        break;
                    }
                }
                if (waitForExit)
                {
                    WaitForExit(process);
                }
            } finally {
                process.Terminate();
            }
        }
コード例 #11
0
        internal async Task <PythonThread> RunAndBreakAsync(string filename, int lineNo, string breakFilename = null, string arguments = "", Action processLoaded = null, PythonDebugOptions debugOptions = PythonDebugOptions.RedirectOutput)
        {
            PythonThread thread;

            var debugger = new PythonDebugger();

            thread = null;
            PythonProcess process = DebugProcess(debugger, DebuggerTestPath + filename, async(newproc, newthread) => {
                var breakPoint = newproc.AddBreakpointByFileExtension(lineNo, breakFilename ?? filename);
                await breakPoint.AddAsync(TimeoutToken());
                thread = newthread;
                processLoaded?.Invoke();
            },
                                                 arguments: arguments,
                                                 debugOptions: debugOptions);

            AutoResetEvent brkHit = new AutoResetEvent(false);

            process.BreakpointHit += (sender, args) => {
                thread = args.Thread;
                brkHit.Set();
            };

            bool ready = false;

            try {
                await process.StartAsync();

                AssertWaited(brkHit);
                ready = true;
            } finally {
                if (!ready)
                {
                    process.Terminate();
                }
            }

            return(thread);
        }
コード例 #12
0
 internal PythonProcess DebugProcess(PythonDebugger debugger, string filename, Func <PythonProcess, PythonThread, Task> onLoaded = null, bool resumeOnProcessLoaded = true, string interpreterOptions = null, PythonDebugOptions debugOptions = PythonDebugOptions.RedirectOutput, string cwd = null, string arguments = "")
 {
     return(debugger.DebugProcess(Version, filename, DebugLog, onLoaded, resumeOnProcessLoaded, interpreterOptions, debugOptions, cwd, arguments));
 }
コード例 #13
0
ファイル: PythonDebugger.cs プロジェクト: omnimark/PTVS
 /// <summary>
 /// Creates a new PythonProcess object for debugging.  The process does not start until Start is called 
 /// on the returned PythonProcess object.
 /// </summary>
 public PythonProcess CreateProcess(PythonLanguageVersion langVersion, string exe, string args, string dir, string env, string interpreterOptions = null, PythonDebugOptions debugOptions = PythonDebugOptions.None) {
     return new PythonProcess(langVersion, exe, args, dir, env, interpreterOptions, debugOptions);
 }
コード例 #14
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)
        {
            process = null;
            if (_mixedMode) {
                return VSConstants.E_NOTIMPL;
            }

            Debug.WriteLine("--------------------------------------------------------------------------------");
            Debug.WriteLine("PythonEngine LaunchSuspended Begin " + launchFlags + " " + GetHashCode());
            AssertMainThread();
            Debug.Assert(_events == null);
            Debug.Assert(_process == null);
            Debug.Assert(_ad7ProgramId == Guid.Empty);

            _events = ad7Callback;
            _engineCreated = _programCreated = false;
            _loadComplete.Reset();

            if (options != null) {
                ParseOptions(options);
            }

            Send(new AD7CustomEvent(VsPackageMessage.SetDebugOptions, this), AD7CustomEvent.IID, null, null);

            // If this is a windowed application, there's no console to wait on, so disable those flags if they were set.
            if (_debugOptions.HasFlag(PythonDebugOptions.IsWindowsApplication)) {
                _debugOptions &= ~(PythonDebugOptions.WaitOnNormalExit | PythonDebugOptions.WaitOnAbnormalExit);
            }

            Guid processId;
            if (_debugOptions.HasFlag(PythonDebugOptions.AttachRunning)) {
                if (!Guid.TryParse(exe, out processId)) {
                    Debug.Fail("When PythonDebugOptions.AttachRunning is used, the 'exe' parameter must be a debug session GUID.");
                    return VSConstants.E_INVALIDARG;
                }

                _process = DebugConnectionListener.GetProcess(processId);
                _attached = true;
                _pseudoAttach = true;
            } else {
                _process = new PythonProcess(_languageVersion, exe, args, dir, env, _interpreterOptions, _debugOptions, _dirMapping);
            }

            if (!_debugOptions.HasFlag(PythonDebugOptions.AttachRunning)) {
                _process.Start(false);
            }

            AttachEvents(_process);

            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;
        }
コード例 #15
0
ファイル: PythonProcess.cs プロジェクト: KevinH-MS/PTVS
 public static PythonProcess Attach(int pid, PythonDebugOptions debugOptions = PythonDebugOptions.None) {
     return new PythonProcess(pid, debugOptions);
 }
コード例 #16
0
        internal static PythonProcess DebugProcess(this PythonDebugger debugger, PythonVersion version, string filename, Func <PythonProcess, PythonThread, Task> onLoaded = null, bool resumeOnProcessLoaded = true, string interpreterOptions = null, PythonDebugOptions debugOptions = PythonDebugOptions.RedirectOutput, string cwd = null, string arguments = "")
        {
            string fullPath = Path.GetFullPath(filename);
            string dir      = cwd ?? Path.GetFullPath(Path.GetDirectoryName(filename));

            if (!String.IsNullOrEmpty(arguments))
            {
                arguments = "\"" + fullPath + "\" " + arguments;
            }
            else
            {
                arguments = "\"" + fullPath + "\"";
            }
            var process = debugger.CreateProcess(version.Version, version.InterpreterPath, arguments, dir, "", interpreterOptions, debugOptions);

            process.DebuggerOutput += (sender, args) => {
                Console.WriteLine("{0}: {1}", args.Thread?.Id, args.Output);
            };
            process.ProcessLoaded += async(sender, args) => {
                if (onLoaded != null)
                {
                    await onLoaded(process, args.Thread);
                }
                if (resumeOnProcessLoaded)
                {
                    await process.ResumeAsync(default(CancellationToken));
                }
            };

            return(process);
        }
コード例 #17
0
ファイル: AD7Engine.cs プロジェクト: zooba/PTVS
 public AD7Engine() {
     _breakpointManager = new BreakpointManager(this);
     _defaultBreakOnExceptionMode = (int)enum_EXCEPTION_STATE.EXCEPTION_STOP_USER_UNCAUGHT;
     _debugOptions = PythonDebugOptions.RichExceptions;
     Debug.WriteLine("Python Engine Created " + GetHashCode());
     _engines.Add(new WeakReference(this));
 }