Ejemplo n.º 1
0
 /// <summary>
 /// Installs virtualenv. If pip is not installed, the returned task will
 /// succeed but error text will be passed to the redirector.
 /// </summary>
 public static Task<bool> Install(IServiceProvider provider, IPythonInterpreterFactory factory, Redirector output = null) {
     bool elevate = provider.GetPythonToolsService().GeneralOptions.ElevatePip;
     if (factory.Configuration.Version < new Version(2, 5)) {
         if (output != null) {
             output.WriteErrorLine("Python versions earlier than 2.5 are not supported by PTVS.");
         }
         throw new OperationCanceledException();
     } else if (factory.Configuration.Version == new Version(2, 5)) {
         return Pip.Install(provider, factory, "https://go.microsoft.com/fwlink/?LinkID=317970", elevate, output);
     } else {
         return Pip.Install(provider, factory, "https://go.microsoft.com/fwlink/?LinkID=317969", elevate, output);
     }
 }
Ejemplo n.º 2
0
        /// <summary>
        /// Runs the file with the provided settings as a user with
        /// administrative permissions. The window is always hidden and output
        /// is provided to the redirector when the process terminates.
        /// </summary>
        /// <param name="filename">Executable file to run.</param>
        /// <param name="arguments">Arguments to pass.</param>
        /// <param name="workingDirectory">Starting directory.</param>
        /// <param name="redirector">
        /// An object to receive redirected output.
        /// </param>
        /// <param name="quoteArgs"></param>
        /// <returns>A <see cref="ProcessOutput"/> object.</returns>
        public static ProcessOutput RunElevated(
            string filename,
            IEnumerable<string> arguments,
            string workingDirectory,
            IEnumerable<KeyValuePair<string, string>> env,
            Redirector redirector,
            bool quoteArgs = true,
            bool elevate = true,
            Encoding outputEncoding = null,
            Encoding errorEncoding = null
        ) {
            var psi = new ProcessStartInfo(PythonToolsInstallPath.GetFile("Microsoft.PythonTools.RunElevated.exe", typeof(ProcessOutput).Assembly));
            psi.CreateNoWindow = true;
            psi.WindowStyle = ProcessWindowStyle.Hidden;
            psi.UseShellExecute = true;
            psi.Verb = elevate ? "runas" : null;

            var utf8 = new UTF8Encoding(false);
            // Send args and env as base64 to avoid newline issues
            string args;
            if (quoteArgs) {
                args = string.Join("|", arguments
                    .Where(a => a != null)
                    .Select(a => Convert.ToBase64String(utf8.GetBytes(QuoteSingleArgument(a))))
                );
            } else {
                args = string.Join("|", arguments
                    .Where(a => a != null)
                    .Select(a => Convert.ToBase64String(utf8.GetBytes(a)))
                );
            }

            var fullEnv = env != null ?
                string.Join("|", env.Select(kv => kv.Key + "=" + Convert.ToBase64String(utf8.GetBytes(kv.Value)))) :
                "";

            TcpListener listener = null;
            Task<TcpClient> clientTask = null;

            for (int retries = 10; retries >= 0; --retries) {
                int port = GetFreePort();
                listener = new TcpListener(IPAddress.Loopback, port);
                psi.Arguments = port.ToString();
                try {
                    listener.Start();
                } catch (SocketException) {
                    if (retries == 0) {
                        throw;
                    }
                    continue;
                }
                try {
                    clientTask = listener.AcceptTcpClientAsync();
                } catch (SocketException) {
                    listener.Stop();
                    if (retries == 0) {
                        throw;
                    }
                    clientTask = null;
                }
            }

            if (clientTask == null) {
                throw new InvalidOperationException(Strings.UnableToElevate);
            }

            var process = new Process();

            clientTask.ContinueWith(t => {
                listener.Stop();
                TcpClient client;
                try {
                    client = t.Result;
                } catch (AggregateException ae) {
                    try {
                        process.Kill();
                    } catch (InvalidOperationException) {
                    } catch (Win32Exception) {
                    }

                    if (redirector != null) {
                        foreach (var ex in ae.InnerExceptions.DefaultIfEmpty(ae)) {
                            using (var reader = new StringReader(ex.ToString())) {
                                for (var line = reader.ReadLine(); line != null; line = reader.ReadLine()) {
                                    redirector.WriteErrorLine(line);
                                }
                            }
                        }
                    }
                    return;
                }
                using (var writer = new StreamWriter(client.GetStream(), utf8, 4096, true)) {
                    writer.WriteLine(filename);
                    writer.WriteLine(args);
                    writer.WriteLine(workingDirectory);
                    writer.WriteLine(fullEnv);
                    writer.WriteLine(outputEncoding?.WebName ?? "");
                    writer.WriteLine(errorEncoding?.WebName ?? "");
                }

                if (redirector != null) {
                    var reader = new StreamReader(client.GetStream(), utf8, false, 4096, true);
                    Task.Run(() => {
                        try {
                            for (var line = reader.ReadLine(); line != null; line = reader.ReadLine()) {
                                if (line.StartsWith("OUT:")) {
                                    redirector.WriteLine(line.Substring(4));
                                } else if (line.StartsWith("ERR:")) {
                                    redirector.WriteErrorLine(line.Substring(4));
                                } else {
                                    redirector.WriteLine(line);
                                }
                            }
                        } catch (IOException) {
                        } catch (ObjectDisposedException) {
                        }
                    });
                }
            });

            process.StartInfo = psi;

            return new ProcessOutput(process, redirector);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Runs the file with the provided settings as a user with
        /// administrative permissions. The window is always hidden and output
        /// is provided to the redirector when the process terminates.
        /// </summary>
        /// <param name="filename">Executable file to run.</param>
        /// <param name="arguments">Arguments to pass.</param>
        /// <param name="workingDirectory">Starting directory.</param>
        /// <param name="redirector">
        /// An object to receive redirected output.
        /// </param>
        /// <param name="quoteArgs"></param>
        /// <returns>A <see cref="ProcessOutput"/> object.</returns>
        public static ProcessOutput RunElevated(
            string filename,
            IEnumerable <string> arguments,
            string workingDirectory,
            IEnumerable <KeyValuePair <string, string> > env,
            Redirector redirector,
            bool quoteArgs          = true,
            bool elevate            = true,
            Encoding outputEncoding = null,
            Encoding errorEncoding  = null
            )
        {
            var psi = new ProcessStartInfo(PythonToolsInstallPath.GetFile("Microsoft.PythonTools.RunElevated.exe", typeof(ProcessOutput).Assembly));

            psi.CreateNoWindow = true;
            psi.WindowStyle    = ProcessWindowStyle.Hidden;

            var utf8 = new UTF8Encoding(false);
            // Send args and env as base64 to avoid newline issues
            string args;

            if (quoteArgs)
            {
                args = string.Join("|", arguments
                                   .Where(a => a != null)
                                   .Select(a => Convert.ToBase64String(utf8.GetBytes(QuoteSingleArgument(a))))
                                   );
            }
            else
            {
                args = string.Join("|", arguments
                                   .Where(a => a != null)
                                   .Select(a => Convert.ToBase64String(utf8.GetBytes(a)))
                                   );
            }

            var fullEnv = env != null?
                          string.Join("|", env.Select(kv => kv.Key + "=" + Convert.ToBase64String(utf8.GetBytes(kv.Value)))) :
                              "";

            TcpListener      listener   = null;
            Task <TcpClient> clientTask = null;

            try {
                listener      = SocketUtils.GetRandomPortListener(IPAddress.Loopback, out int port);
                psi.Arguments = port.ToString();
                clientTask    = listener.AcceptTcpClientAsync();
            } catch (Exception ex) {
                listener?.Stop();
                throw new InvalidOperationException(Strings.UnableToElevate, ex);
            }

            var process = new Process();

            clientTask.ContinueWith(t => {
                listener.Stop();
                TcpClient client;
                try {
                    client = t.Result;
                } catch (AggregateException ae) {
                    try {
                        process.Kill();
                    } catch (InvalidOperationException) {
                    } catch (Win32Exception) {
                    }

                    if (redirector != null)
                    {
                        foreach (var ex in ae.InnerExceptions.DefaultIfEmpty(ae))
                        {
                            using (var reader = new StringReader(ex.ToString())) {
                                for (var line = reader.ReadLine(); line != null; line = reader.ReadLine())
                                {
                                    redirector.WriteErrorLine(line);
                                }
                            }
                        }
                    }
                    return;
                }
                using (var writer = new StreamWriter(client.GetStream(), utf8, 4096, true)) {
                    writer.WriteLine(filename);
                    writer.WriteLine(args);
                    writer.WriteLine(workingDirectory);
                    writer.WriteLine(fullEnv);
                    writer.WriteLine(outputEncoding?.WebName ?? "");
                    writer.WriteLine(errorEncoding?.WebName ?? "");
                }

                if (redirector != null)
                {
                    Task.Run(() => {
                        using (var reader = new StreamReader(client.GetStream(), utf8, false, 4096, true)) {
                            try {
                                string line;
                                while ((line = reader.ReadLine()) != null)
                                {
                                    if (line.StartsWithOrdinal("OUT:"))
                                    {
                                        redirector.WriteLine(line.Substring(4));
                                    }
                                    else if (line.StartsWithOrdinal("ERR:"))
                                    {
                                        redirector.WriteErrorLine(line.Substring(4));
                                    }
                                    else
                                    {
                                        redirector.WriteLine(line);
                                    }
                                }
                            } catch (IOException) {
                            } catch (ObjectDisposedException) {
                            }
                        }
                    });
                }
            });

            process.StartInfo = psi;

            return(new ProcessOutput(process, redirector));
        }
Ejemplo n.º 4
0
        private ProcessOutput(Process process, Redirector redirector)
        {
            _arguments  = QuoteSingleArgument(process.StartInfo.FileName) + " " + process.StartInfo.Arguments;
            _redirector = redirector;
            if (_redirector == null)
            {
                _output     = new List <string>();
                _error      = new List <string>();
                _redirector = new ListRedirector(_output, _error);
            }

            _process = process;
            if (_process.StartInfo.RedirectStandardOutput)
            {
                _process.OutputDataReceived += OnOutputDataReceived;
            }
            if (_process.StartInfo.RedirectStandardError)
            {
                _process.ErrorDataReceived += OnErrorDataReceived;
            }

            if (!_process.StartInfo.RedirectStandardOutput && !_process.StartInfo.RedirectStandardError)
            {
                // If we are receiving output events, we signal that the process
                // has exited when one of them receives null. Otherwise, we have
                // to listen for the Exited event.
                // If we just listen for the Exited event, we may receive it
                // before all the output has arrived.
                _process.Exited += OnExited;
            }
            _process.EnableRaisingEvents = true;

            try {
                _process.Start();
            } catch (Win32Exception ex) {
                _redirector.WriteErrorLine(ex.Message);
                _process = null;
            } catch (Exception ex) when(!ex.IsCriticalException())
            {
                foreach (var line in SplitLines(ex.ToString()))
                {
                    _redirector.WriteErrorLine(line);
                }
                _process = null;
            }

            if (_process != null)
            {
                if (_process.StartInfo.RedirectStandardOutput)
                {
                    _process.BeginOutputReadLine();
                }
                if (_process.StartInfo.RedirectStandardError)
                {
                    _process.BeginErrorReadLine();
                }

                if (_process.StartInfo.RedirectStandardInput)
                {
                    // Close standard input so that we don't get stuck trying to read input from the user.
                    try {
                        _process.StandardInput.Close();
                    } catch (InvalidOperationException) {
                        // StandardInput not available
                    }
                }
            }
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Runs the file with the provided settings as a user with
        /// administrative permissions. The window is always hidden and output
        /// is provided to the redirector when the process terminates.
        /// </summary>
        /// <param name="filename">Executable file to run.</param>
        /// <param name="arguments">Arguments to pass.</param>
        /// <param name="workingDirectory">Starting directory.</param>
        /// <param name="redirector">
        /// An object to receive redirected output.
        /// </param>
        /// <param name="quoteArgs"></param>
        /// <returns>A <see cref="ProcessOutput"/> object.</returns>
        public static ProcessOutput RunElevated(
            string filename,
            IEnumerable <string> arguments,
            string workingDirectory,
            Redirector redirector,
            bool quoteArgs          = true,
            Encoding outputEncoding = null,
            Encoding errorEncoding  = null
            )
        {
            var outFile = Path.GetTempFileName();
            var errFile = Path.GetTempFileName();
            var psi     = new ProcessStartInfo("cmd.exe");

            psi.CreateNoWindow  = true;
            psi.WindowStyle     = ProcessWindowStyle.Hidden;
            psi.UseShellExecute = true;
            psi.Verb            = "runas";

            string args;

            if (quoteArgs)
            {
                args = string.Join(" ", arguments.Where(a => a != null).Select(QuoteSingleArgument));
            }
            else
            {
                args = string.Join(" ", arguments.Where(a => a != null));
            }
            psi.Arguments = string.Format("/S /C \"{0} {1} >>{2} 2>>{3}\"",
                                          QuoteSingleArgument(filename),
                                          args,
                                          QuoteSingleArgument(outFile),
                                          QuoteSingleArgument(errFile)
                                          );
            psi.WorkingDirectory = workingDirectory;
            psi.CreateNoWindow   = true;
            psi.UseShellExecute  = true;

            var process = new Process();

            process.StartInfo = psi;
            var result = new ProcessOutput(process, redirector);

            if (redirector != null)
            {
                result.Exited += (s, e) => {
                    try {
                        try {
                            var lines = File.ReadAllLines(outFile, outputEncoding ?? Encoding.Default);
                            foreach (var line in lines)
                            {
                                redirector.WriteLine(line);
                            }
                        } catch (Exception ex) when(!ex.IsCriticalException())
                        {
                            redirector.WriteErrorLine("Failed to obtain standard output from elevated process.");
#if DEBUG
                            foreach (var line in SplitLines(ex.ToString()))
                            {
                                redirector.WriteErrorLine(line);
                            }
#else
                            Trace.TraceError("Failed to obtain standard output from elevated process.");
                            Trace.TraceError(ex.ToString());
#endif
                        }
                        try {
                            var lines = File.ReadAllLines(errFile, errorEncoding ?? outputEncoding ?? Encoding.Default);
                            foreach (var line in lines)
                            {
                                redirector.WriteErrorLine(line);
                            }
                        } catch (Exception ex) when(!ex.IsCriticalException())
                        {
                            redirector.WriteErrorLine("Failed to obtain standard error from elevated process.");
#if DEBUG
                            foreach (var line in SplitLines(ex.ToString()))
                            {
                                redirector.WriteErrorLine(line);
                            }
#else
                            Trace.TraceError("Failed to obtain standard error from elevated process.");
                            Trace.TraceError(ex.ToString());
#endif
                        }
                    } finally {
                        try {
                            File.Delete(outFile);
                        } catch { }
                        try {
                            File.Delete(errFile);
                        } catch { }
                    }
                };
            }
            return(result);
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Runs the file with the provided settings as a user with
        /// administrative permissions. The window is always hidden and output
        /// is provided to the redirector when the process terminates.
        /// </summary>
        /// <param name="filename">Executable file to run.</param>
        /// <param name="arguments">Arguments to pass.</param>
        /// <param name="workingDirectory">Starting directory.</param>
        /// <param name="redirector">
        /// An object to receive redirected output.
        /// </param>
        /// <param name="quoteArgs"></param>
        /// <returns>A <see cref="ProcessOutput"/> object.</returns>
        public static ProcessOutput RunElevated(
            string filename,
            IEnumerable <string> arguments,
            string workingDirectory,
            IEnumerable <KeyValuePair <string, string> > env,
            Redirector redirector,
            bool quoteArgs          = true,
            bool elevate            = true,
            Encoding outputEncoding = null,
            Encoding errorEncoding  = null
            )
        {
            var psi = new ProcessStartInfo(PythonToolsInstallPath.GetFile("Microsoft.PythonTools.RunElevated.exe", typeof(ProcessOutput).Assembly));

            psi.CreateNoWindow  = true;
            psi.WindowStyle     = ProcessWindowStyle.Hidden;
            psi.UseShellExecute = true;
            psi.Verb            = elevate ? "runas" : null;

            int port     = GetFreePort();
            var listener = new TcpListener(IPAddress.Loopback, port);

            psi.Arguments = port.ToString();

            var utf8 = new UTF8Encoding(false);
            // Send args and env as base64 to avoid newline issues
            string args;

            if (quoteArgs)
            {
                args = string.Join("|", arguments
                                   .Where(a => a != null)
                                   .Select(a => Convert.ToBase64String(utf8.GetBytes(QuoteSingleArgument(a))))
                                   );
            }
            else
            {
                args = string.Join("|", arguments
                                   .Where(a => a != null)
                                   .Select(a => Convert.ToBase64String(utf8.GetBytes(a)))
                                   );
            }

            var fullEnv = env != null?
                          string.Join("|", env.Select(kv => kv.Key + "=" + Convert.ToBase64String(utf8.GetBytes(kv.Value)))) :
                              "";

            listener.Start();
            listener.AcceptTcpClientAsync().ContinueWith(t => {
                listener.Stop();
                var client = t.Result;
                using (var writer = new StreamWriter(client.GetStream(), utf8, 4096, true)) {
                    writer.WriteLine(filename);
                    writer.WriteLine(args);
                    writer.WriteLine(workingDirectory);
                    writer.WriteLine(fullEnv);
                    writer.WriteLine(outputEncoding?.WebName ?? "");
                    writer.WriteLine(errorEncoding?.WebName ?? "");
                }

                if (redirector != null)
                {
                    var reader = new StreamReader(client.GetStream(), utf8, false, 4096, true);
                    Task.Run(() => {
                        try {
                            for (var line = reader.ReadLine(); line != null; line = reader.ReadLine())
                            {
                                if (line.StartsWith("OUT:"))
                                {
                                    redirector.WriteLine(line.Substring(4));
                                }
                                else if (line.StartsWith("ERR:"))
                                {
                                    redirector.WriteErrorLine(line.Substring(4));
                                }
                                else
                                {
                                    redirector.WriteLine(line);
                                }
                            }
                        } catch (IOException) {
                        } catch (ObjectDisposedException) {
                        }
                    });
                }
            });

            var process = new Process();

            process.StartInfo = psi;

            return(new ProcessOutput(process, redirector));
        }
Ejemplo n.º 7
0
        private ProcessOutput(Process process, Redirector redirector) {
            _arguments = QuoteSingleArgument(process.StartInfo.FileName) + " " + process.StartInfo.Arguments;
            _redirector = redirector;
            if (_redirector == null) {
                _output = new List<string>();
                _error = new List<string>();
            }

            _process = process;
            if (_process.StartInfo.RedirectStandardOutput) {
                _process.OutputDataReceived += OnOutputDataReceived;
            }
            if (_process.StartInfo.RedirectStandardError) {
                _process.ErrorDataReceived += OnErrorDataReceived;
            }

            if (!_process.StartInfo.RedirectStandardOutput && !_process.StartInfo.RedirectStandardError) {
                // If we are receiving output events, we signal that the process
                // has exited when one of them receives null. Otherwise, we have
                // to listen for the Exited event.
                // If we just listen for the Exited event, we may receive it
                // before all the output has arrived.
                _process.Exited += OnExited;
            }
            _process.EnableRaisingEvents = true;

            try {
                _process.Start();
            } catch (Exception ex) when (!ex.IsCriticalException()) {
                if (_redirector != null) {
                    foreach (var line in SplitLines(ex.ToString())) {
                        _redirector.WriteErrorLine(line);
                    }
                } else if (_error != null) {
                    _error.AddRange(SplitLines(ex.ToString()));
                }
                _process = null;
            }

            if (_process != null) {
                if (_process.StartInfo.RedirectStandardOutput) {
                    _process.BeginOutputReadLine();
                }
                if (_process.StartInfo.RedirectStandardError) {
                    _process.BeginErrorReadLine();
                }
                
                if (_process.StartInfo.RedirectStandardInput) {
                    // Close standard input so that we don't get stuck trying to read input from the user.
                    try {
                        _process.StandardInput.Close();
                    } catch (InvalidOperationException) {
                        // StandardInput not available
                    }
                }
            }
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Runs the file with the provided settings as a user with
        /// administrative permissions. The window is always hidden and output
        /// is provided to the redirector when the process terminates.
        /// </summary>
        /// <param name="filename">Executable file to run.</param>
        /// <param name="arguments">Arguments to pass.</param>
        /// <param name="workingDirectory">Starting directory.</param>
        /// <param name="redirector">
        /// An object to receive redirected output.
        /// </param>
        /// <param name="quoteArgs"></param>
        /// <returns>A <see cref="ProcessOutput"/> object.</returns>
        public static ProcessOutput RunElevated(
            string filename,
            IEnumerable<string> arguments,
            string workingDirectory,
            Redirector redirector,
            bool quoteArgs = true,
            Encoding outputEncoding = null,
            Encoding errorEncoding = null
        ) {
            var outFile = Path.GetTempFileName();
            var errFile = Path.GetTempFileName();
            var psi = new ProcessStartInfo("cmd.exe");
            psi.CreateNoWindow = true;
            psi.WindowStyle = ProcessWindowStyle.Hidden;
            psi.UseShellExecute = true;
            psi.Verb = "runas";

            string args;
            if (quoteArgs) {
                args = string.Join(" ", arguments.Where(a => a != null).Select(QuoteSingleArgument));
            } else {
                args = string.Join(" ", arguments.Where(a => a != null));
            }
            psi.Arguments = string.Format("/S /C \"{0} {1} >>{2} 2>>{3}\"",
                QuoteSingleArgument(filename),
                args,
                QuoteSingleArgument(outFile),
                QuoteSingleArgument(errFile)
            );
            psi.WorkingDirectory = workingDirectory;
            psi.CreateNoWindow = true;
            psi.UseShellExecute = true;

            var process = new Process();
            process.StartInfo = psi;
            var result = new ProcessOutput(process, redirector);
            if (redirector != null) {
                result.Exited += (s, e) => {
                    try {
                        try {
                            var lines = File.ReadAllLines(outFile, outputEncoding ?? Encoding.Default);
                            foreach (var line in lines) {
                                redirector.WriteLine(line);
                            }
                        } catch (Exception ex) when(!ex.IsCriticalException()) {
                            redirector.WriteErrorLine("Failed to obtain standard output from elevated process.");
#if DEBUG
                            foreach (var line in SplitLines(ex.ToString())) {
                                redirector.WriteErrorLine(line);
                            }
#else
                            Trace.TraceError("Failed to obtain standard output from elevated process.");
                            Trace.TraceError(ex.ToString());
#endif
                        }
                        try {
                            var lines = File.ReadAllLines(errFile, errorEncoding ?? outputEncoding ?? Encoding.Default);
                            foreach (var line in lines) {
                                redirector.WriteErrorLine(line);
                            }
                        } catch (Exception ex) when(!ex.IsCriticalException()) {
                            redirector.WriteErrorLine("Failed to obtain standard error from elevated process.");
#if DEBUG
                            foreach (var line in SplitLines(ex.ToString())) {
                                redirector.WriteErrorLine(line);
                            }
#else
                            Trace.TraceError("Failed to obtain standard error from elevated process.");
                            Trace.TraceError(ex.ToString());
#endif
                        }
                    } finally {
                        try {
                            File.Delete(outFile);
                        } catch { }
                        try {
                            File.Delete(errFile);
                        } catch { }
                    }
                };
            }
            return result;
        }
Ejemplo n.º 9
0
 private static string GetInsecureArg(
     IPythonInterpreterFactory factory,
     Redirector output = null
 ) {
     if (!IsSecureInstall(factory)) {
         // Python 2.5 does not include ssl, and so the --insecure
         // option is required to use pip.
         if (output != null) {
             output.WriteErrorLine("Using '--insecure' option for Python 2.5.");
         }
         return "--insecure";
     }
     return null;
 }