Beispiel #1
0
        protected override async Task <CommandProcessorThread> ConnectAsync(CancellationToken ct)
        {
            var remoteProcess = _process as PythonRemoteProcess;

            try {
                _serviceProvider.GetPythonToolsService().Logger.LogEvent(Logging.PythonLogEvent.DebugRepl, new Logging.DebugReplInfo {
                    RemoteProcess = remoteProcess != null,
                    Version       = _process.LanguageVersion.ToVersion().ToString()
                });
            } catch (Exception ex) {
                Debug.Fail(ex.ToUnhandledExceptionMessage(GetType()));
            }

            if (remoteProcess == null)
            {
                var conn = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
                conn.Bind(new IPEndPoint(IPAddress.Loopback, 0));
                conn.Listen(0);
                var portNum = ((IPEndPoint)conn.LocalEndPoint).Port;
                var proc    = System.Diagnostics.Process.GetProcessById(_process.Id);

                var thread = CommandProcessorThread.Create(this, conn, proc);
                await _process.ConnectReplAsync(portNum);

                return(thread);
            }

            // Ignore SSL errors, since user was already prompted about them and chose to ignore them when he attached to this process.
            using (var debugConn = await remoteProcess.ConnectAsync(false, ct)) {
                // After the REPL attach response is received, we go from
                // using the debugger protocol to the REPL protocol.
                // It's important to have a clean break between the 2, and at the right time.
                // The server will send the debugger protocol response for attach
                // before sending anything else and as soon as we read that
                // response, we stop reading any more messages.
                // Then we give the stream to the REPL protocol handler.
                try {
                    var response = await debugConn.SendRequestAsync(new LDP.RemoteReplAttachRequest(), ct, resp => {
                        Debug.WriteLine("Stopping debug connection message processing. Switching from debugger protocol to REPL protocol.");

                        // This causes the message handling loop to exit
                        throw new OperationCanceledException();
                    });

                    if (!response.accepted)
                    {
                        WriteError(Strings.ConnErrorMessages_RemoteAttachRejected);
                        return(null);
                    }

                    // Get the stream out of the connection before Dispose is called,
                    // so that the stream doesn't get closed.
                    var stream = debugConn.DetachStream();
                    return(CommandProcessorThread.Create(this, stream));
                } catch (FailedRequestException ex) {
                    WriteError(ex.Message);
                    return(null);
                }
            }
        }
        protected override CommandProcessorThread Connect()
        {
            var remoteProcess = _process as PythonRemoteProcess;

            if (remoteProcess == null)
            {
                var conn = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
                conn.Bind(new IPEndPoint(IPAddress.Loopback, 0));
                conn.Listen(0);
                var portNum = ((IPEndPoint)conn.LocalEndPoint).Port;
                var proc    = System.Diagnostics.Process.GetProcessById(_process.Id);

                var thread = CommandProcessorThread.Create(this, conn, proc);
                _process.ConnectRepl(portNum);
                return(thread);
            }

            // Ignore SSL errors, since user was already prompted about them and chose to ignore them when he attached to this process.
            var  stream    = remoteProcess.Connect(false);
            bool connected = false;

            try {
                stream.Write(PythonRemoteProcess.ReplCommandBytes);

                string attachResp = stream.ReadAsciiString(PythonRemoteProcess.Accepted.Length);
                if (attachResp != PythonRemoteProcess.Accepted)
                {
                    throw new ConnectionException(ConnErrorMessages.RemoteAttachRejected);
                }

                connected = true;
            } finally {
                if (!connected)
                {
                    if (stream != null)
                    {
                        stream.Close();
                    }
                    stream = null;
                }
            }

            return(CommandProcessorThread.Create(this, stream));
        }
        protected virtual Task <CommandProcessorThread> ConnectAsync(CancellationToken ct)
        {
            _serviceProvider.GetUIThread().MustBeCalledFromUIThreadOrThrow();

            var interpreterPath = Configuration?.GetInterpreterPath();

            if (string.IsNullOrWhiteSpace(interpreterPath))
            {
                WriteError(Strings.ReplEvaluatorInterpreterNotConfigured.FormatUI(DisplayName));
                return(null);
            }
            else if (!File.Exists(interpreterPath))
            {
                WriteError(Strings.ReplEvaluatorInterpreterNotFound);
                return(null);
            }

            var processInfo = new ProcessStartInfo(interpreterPath);

#if DEBUG
            bool debugMode = Environment.GetEnvironmentVariable("_PTVS_DEBUG_REPL") != null;
            processInfo.CreateNoWindow         = !debugMode;
            processInfo.UseShellExecute        = debugMode;
            processInfo.RedirectStandardOutput = !debugMode;
            processInfo.RedirectStandardError  = !debugMode;
            processInfo.RedirectStandardInput  = !debugMode;
#else
            processInfo.CreateNoWindow         = true;
            processInfo.UseShellExecute        = false;
            processInfo.RedirectStandardOutput = true;
            processInfo.RedirectStandardError  = true;
            processInfo.RedirectStandardInput  = true;
#endif

            var conn = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
            conn.Bind(new IPEndPoint(IPAddress.Loopback, 0));
            conn.Listen(0);
            var portNum = ((IPEndPoint)conn.LocalEndPoint).Port;

            var workingDirectory = Configuration.WorkingDirectory;
            if (!string.IsNullOrEmpty(workingDirectory))
            {
                processInfo.WorkingDirectory = workingDirectory;
            }
            else
            {
                processInfo.WorkingDirectory = CommonUtils.GetParent(processInfo.FileName);
            }

#if DEBUG
            if (!debugMode)
            {
#endif
            var env = processInfo.Environment;
            foreach (var kv in _serviceProvider.GetPythonToolsService().GetFullEnvironment(Configuration))
            {
                env[kv.Key] = kv.Value;
            }
#if DEBUG
        }
#endif

            var args = new List <string>();
            var interpreterArguments = Configuration.InterpreterArguments;
            if (!string.IsNullOrWhiteSpace(interpreterArguments))
            {
                args.Add(interpreterArguments);
            }

            args.Add(ProcessOutput.QuoteSingleArgument(PythonToolsInstallPath.GetFile("visualstudio_py_repl.py")));
            args.Add("--port");
            args.Add(portNum.ToString());

            args.Add("--execution-mode");
            args.Add(string.IsNullOrEmpty(BackendName) ? "standard" : BackendName);

            processInfo.Arguments = string.Join(" ", args);

            Process process;
            try {
                if (!File.Exists(processInfo.FileName))
                {
                    throw new Win32Exception(Microsoft.VisualStudioTools.Project.NativeMethods.ERROR_FILE_NOT_FOUND);
                }
                process = Process.Start(processInfo);
                if (process.WaitForExit(100))
                {
                    throw new Win32Exception(process.ExitCode);
                }
            } catch (Win32Exception e) {
                if (e.NativeErrorCode == Microsoft.VisualStudioTools.Project.NativeMethods.ERROR_FILE_NOT_FOUND)
                {
                    WriteError(Strings.ReplEvaluatorInterpreterNotFound);
                }
                else
                {
                    WriteError(Strings.ErrorStartingInteractiveProcess.FormatUI(e.ToString()));
                }
                return(null);
            } catch (Exception e) when(!e.IsCriticalException())
            {
                return(null);
            }

            return(Task.FromResult(CommandProcessorThread.Create(this, conn, process)));
        }