コード例 #1
0
ファイル: CookiecutterClient.cs プロジェクト: jsschultz/PTVS
 public CookiecutterClient(CookiecutterPythonInterpreter interpreter, Redirector redirector) {
     _interpreter = interpreter;
     var localAppDataFolderPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
     _envFolderPath = Path.Combine(localAppDataFolderPath, "Microsoft", "CookiecutterTools", "env");
     _envInterpreterPath = Path.Combine(_envFolderPath, "scripts", "python.exe");
     _redirector = redirector;
 }
コード例 #2
0
        public static ICookiecutterClient Create(IServiceProvider provider, Redirector redirector) {
            var interpreter = FindCompatibleInterpreter();
            if (interpreter != null) {
                return new CookiecutterClient(provider, interpreter, redirector);
            }

            return null;
        }
コード例 #3
0
        protected override void OnCreate() {
            _outputWindow = OutputWindowRedirector.GetGeneral(this);
            Debug.Assert(_outputWindow != null);
            _statusBar = GetService(typeof(SVsStatusbar)) as IVsStatusbar;
            _uiShell = GetService(typeof(SVsUIShell)) as IVsUIShell;
            _dte = GetService(typeof(EnvDTE.DTE)) as EnvDTE.DTE;
            _infoBarFactory = GetService(typeof(SVsInfoBarUIFactory)) as IVsInfoBarUIFactory;

            object control = null;

            if (!CookiecutterClientProvider.IsCompatiblePythonAvailable()) {
                ReportPrereqsEvent(false);
                control = new MissingDependencies();
            } else {
                ReportPrereqsEvent(true);
                string feedUrl = CookiecutterPackage.Instance.RecommendedFeed;
                if (string.IsNullOrEmpty(feedUrl)) {
                    feedUrl = UrlConstants.DefaultRecommendedFeed;
                }

                _cookiecutterControl = new CookiecutterControl(_outputWindow, CookiecutterTelemetry.Current, new Uri(feedUrl), OpenGeneratedFolder, UpdateCommandUI);
                _cookiecutterControl.ContextMenuRequested += OnContextMenuRequested;
                control = _cookiecutterControl;
                _cookiecutterControl.InitializeAsync(CookiecutterPackage.Instance.CheckForTemplateUpdate).HandleAllExceptions(this, GetType()).DoNotWait();
            }

            Content = control;

            RegisterCommands(new Command[] {
                new HomeCommand(this),
                new RunCommand(this),
                new UpdateCommand(this),
                new CheckForUpdatesCommand(this),
                new GitHubCommand(this, PackageIds.cmdidLinkGitHubHome),
                new GitHubCommand(this, PackageIds.cmdidLinkGitHubIssues),
                new GitHubCommand(this, PackageIds.cmdidLinkGitHubWiki),
            }, PackageGuids.guidCookiecutterCmdSet);

            RegisterCommands(new Command[] {
                new DeleteInstalledTemplateCommand(this),
            }, VSConstants.GUID_VSStandardCommandSet97);

            base.OnCreate();

            OleMenuCommandService mcs = GetService(typeof(IMenuCommandService)) as OleMenuCommandService;

            if (CookiecutterPackage.Instance.ShowHelp) {
                AddInfoBar();
            }
        }
コード例 #4
0
        public CookiecutterControl(Redirector outputWindow, ICookiecutterTelemetry telemetry, Uri feedUrl, Action<string> openFolder, Action updateCommandUI) {
            _updateCommandUI = updateCommandUI;

            _checkForUpdatesTimer = new DispatcherTimer();
            _checkForUpdatesTimer.Tick += new EventHandler(CheckForUpdateTimer_Tick);

            string gitExeFilePath = GitClient.RecommendedGitFilePath;
            var gitClient = new GitClient(gitExeFilePath, outputWindow);
            var gitHubClient = new GitHubClient();
            ViewModel = new CookiecutterViewModel(
                CookiecutterClientProvider.Create(outputWindow),
                gitHubClient,
                gitClient,
                telemetry,
                outputWindow,
                new LocalTemplateSource(CookiecutterViewModel.DefaultInstalledFolderPath, gitClient),
                new FeedTemplateSource(feedUrl),
                new GitHubTemplateSource(gitHubClient),
                openFolder
            );

            ViewModel.UserConfigFilePath = CookiecutterViewModel.GetUserConfigPath();
            ViewModel.OutputFolderPath = string.Empty; // leaving this empty for now, force user to enter one
            ViewModel.ContextLoaded += ViewModel_ContextLoaded;
            ViewModel.HomeClicked += ViewModel_HomeClicked;

            _searchPage = new CookiecutterSearchPage { DataContext = ViewModel };
            _optionsPage = new CookiecutterOptionsPage { DataContext = ViewModel };

            var pages = new List<Page>();
            pages.Add(_searchPage);
            pages.Add(_optionsPage);

            _pageSequence = new CollectionViewSource {
                Source = new ObservableCollection<Page>(pages)
            };
            PageCount = _pageSequence.View.OfType<object>().Count();

            PageSequence = _pageSequence.View;
            PageSequence.MoveCurrentToFirst();

            DataContext = this;

            InitializeComponent();

            _searchPage.SelectedTemplateChanged += SearchPage_SelectedTemplateChanged;
        }
コード例 #5
0
ファイル: GitClientProvider.cs プロジェクト: zooba/PTVS
        public static IGitClient Create(Redirector redirector, string commonIdeFolderPath) {
            string gitExeFilePath = null;

            // Try to locate Team Explorer's git.exe using the running instance ide folder
            if (!string.IsNullOrEmpty(commonIdeFolderPath)) {
                gitExeFilePath = GetTeamExplorerGitFilePathFromIdeFolderPath(commonIdeFolderPath);
            }

            // Try to locate Team Explorer's git.exe using the Dev 15 install path from registry
            // (for tests with no running instance of VS, or when running in Dev 14)
            if (!File.Exists(gitExeFilePath)) {
                gitExeFilePath = GetTeamExplorerGitFilePathFromRegistry();
            }

            // Just use git.exe, and it will work if it's in PATH
            // If it's not, the error will be output in redirector at time of use
            if (!File.Exists(gitExeFilePath)) {
                gitExeFilePath = GitExecutableName;
            }

            return new GitClient(gitExeFilePath, redirector);
        }
コード例 #6
0
ファイル: GitClient.cs プロジェクト: jsschultz/PTVS
 public GitClient(string gitExeFilePath, Redirector redirector) {
     _gitExeFilePath = gitExeFilePath;
     _redirector = redirector;
 }
コード例 #7
0
ファイル: MockGitClient.cs プロジェクト: jsschultz/PTVS
 public Task<string> CloneAsync(Redirector redirector, string repoUrl, string targetParentFolderPath) {
     throw new NotImplementedException();
 }
コード例 #8
0
ファイル: CookiecutterViewModel.cs プロジェクト: zooba/PTVS
        public CookiecutterViewModel(ICookiecutterClient cutter, IGitHubClient githubClient, IGitClient gitClient, ICookiecutterTelemetry telemetry, Redirector outputWindow, ILocalTemplateSource installedTemplateSource, ITemplateSource feedTemplateSource, ITemplateSource gitHubTemplateSource, Action<string> openFolder, IProjectSystemClient projectSystemClient) {
            _cutterClient = cutter;
            _githubClient = githubClient;
            _gitClient = gitClient;
            _telemetry = telemetry;
            _outputWindow = outputWindow;
            _recommendedSource = feedTemplateSource;
            _installedSource = installedTemplateSource;
            _githubSource = gitHubTemplateSource;
            _openFolder = openFolder;
            _projectSystemClient = projectSystemClient;

            Installed = new CategorizedViewModel(Strings.TemplateCategoryInstalled);
            Recommended = new CategorizedViewModel(Strings.TemplateCategoryRecommended);
            GitHub = new CategorizedViewModel(Strings.TemplateCategoryGitHub);
            Custom = new CategorizedViewModel(Strings.TemplateCategoryCustom);
        }
コード例 #9
0
ファイル: CookiecutterClient.cs プロジェクト: zooba/PTVS
 private static async Task<ProcessOutputResult> RunGenerateContextScript(Redirector redirector, string interpreterPath, string templateFolderPath, string userConfigFilePath) {
     var scriptPath = PythonToolsInstallPath.GetFile("cookiecutter_load.py");
     return await RunPythonScript(redirector, interpreterPath, scriptPath, string.Format("\"{0}\" \"{1}\"", templateFolderPath, userConfigFilePath));
 }
コード例 #10
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)
                {
                    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.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));
        }
コード例 #11
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
                    }
                }
            }
        }
コード例 #12
0
ファイル: CookiecutterClient.cs プロジェクト: zooba/PTVS
 private static async Task<ProcessOutputResult> RunRunScript(Redirector redirector, string interpreterPath, string templateFolderPath, string userConfigFilePath, string outputFolderPath, string contextPath) {
     var scriptPath = PythonToolsInstallPath.GetFile("cookiecutter_run.py");
     return await RunPythonScript(redirector, interpreterPath, scriptPath, GetRunArguments(templateFolderPath, userConfigFilePath, outputFolderPath, contextPath));
 }
コード例 #13
0
        /// <summary>
        /// Runs the file with the provided settings.
        /// </summary>
        /// <param name="filename">Executable file to run.</param>
        /// <param name="arguments">Arguments to pass.</param>
        /// <param name="workingDirectory">Starting directory.</param>
        /// <param name="env">Environment variables to set.</param>
        /// <param name="visible">
        /// False to hide the window and redirect output to
        /// <see cref="StandardOutputLines"/> and
        /// <see cref="StandardErrorLines"/>.
        /// </param>
        /// <param name="redirector">
        /// An object to receive redirected output.
        /// </param>
        /// <param name="quoteArgs">
        /// True to ensure each argument is correctly quoted.
        /// </param>
        /// <param name="elevate">
        /// True to run the process as an administrator. See
        /// <see cref="RunElevated"/>.
        /// </param>
        /// <returns>A <see cref="ProcessOutput"/> object.</returns>
        public static ProcessOutput Run(
            string filename,
            IEnumerable <string> arguments,
            string workingDirectory,
            IEnumerable <KeyValuePair <string, string> > env,
            bool visible,
            Redirector redirector,
            bool quoteArgs          = true,
            bool elevate            = false,
            Encoding outputEncoding = null,
            Encoding errorEncoding  = null
            )
        {
            if (string.IsNullOrEmpty(filename))
            {
                throw new ArgumentException("Filename required", "filename");
            }
            if (elevate)
            {
                return(RunElevated(
                           filename,
                           arguments,
                           workingDirectory,
                           env,
                           redirector,
                           quoteArgs,
                           elevate,
                           outputEncoding,
                           errorEncoding
                           ));
            }

            var psi = new ProcessStartInfo(filename);

            if (quoteArgs)
            {
                psi.Arguments = string.Join(" ",
                                            arguments.Where(a => a != null).Select(QuoteSingleArgument));
            }
            else
            {
                psi.Arguments = string.Join(" ", arguments.Where(a => a != null));
            }
            psi.WorkingDirectory       = workingDirectory;
            psi.CreateNoWindow         = !visible;
            psi.UseShellExecute        = false;
            psi.RedirectStandardError  = !visible || (redirector != null);
            psi.RedirectStandardOutput = !visible || (redirector != null);
            psi.RedirectStandardInput  = !visible;
            psi.StandardOutputEncoding = outputEncoding ?? psi.StandardOutputEncoding;
            psi.StandardErrorEncoding  = errorEncoding ?? outputEncoding ?? psi.StandardErrorEncoding;
            if (env != null)
            {
                foreach (var kv in env)
                {
                    psi.EnvironmentVariables[kv.Key] = kv.Value;
                }
            }

            var process = new Process {
                StartInfo = psi
            };

            return(new ProcessOutput(process, redirector));
        }
コード例 #14
0
ファイル: ProcessOutput.cs プロジェクト: jsschultz/PTVS
        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 (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
                    }
                }
            }
        }
コード例 #15
0
ファイル: ProcessOutput.cs プロジェクト: jsschultz/PTVS
        /// <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);
        }
コード例 #16
0
ファイル: ProcessOutput.cs プロジェクト: jsschultz/PTVS
        /// <summary>
        /// Runs the file with the provided settings.
        /// </summary>
        /// <param name="filename">Executable file to run.</param>
        /// <param name="arguments">Arguments to pass.</param>
        /// <param name="workingDirectory">Starting directory.</param>
        /// <param name="env">Environment variables to set.</param>
        /// <param name="visible">
        /// False to hide the window and redirect output to
        /// <see cref="StandardOutputLines"/> and
        /// <see cref="StandardErrorLines"/>.
        /// </param>
        /// <param name="redirector">
        /// An object to receive redirected output.
        /// </param>
        /// <param name="quoteArgs">
        /// True to ensure each argument is correctly quoted.
        /// </param>
        /// <param name="elevate">
        /// True to run the process as an administrator. See
        /// <see cref="RunElevated"/>.
        /// </param>
        /// <returns>A <see cref="ProcessOutput"/> object.</returns>
        public static ProcessOutput Run(
            string filename,
            IEnumerable<string> arguments,
            string workingDirectory,
            IEnumerable<KeyValuePair<string, string>> env,
            bool visible,
            Redirector redirector,
            bool quoteArgs = true,
            bool elevate = false,
            Encoding outputEncoding = null,
            Encoding errorEncoding = null
        ) {
            if (string.IsNullOrEmpty(filename)) {
                throw new ArgumentException("Filename required", "filename");
            }
            if (elevate) {
                return RunElevated(
                    filename,
                    arguments,
                    workingDirectory,
                    env,
                    redirector,
                    quoteArgs,
                    elevate,
                    outputEncoding,
                    errorEncoding
                );
            }

            var psi = new ProcessStartInfo(filename);
            if (quoteArgs) {
                psi.Arguments = string.Join(" ",
                    arguments.Where(a => a != null).Select(QuoteSingleArgument));
            } else {
                psi.Arguments = string.Join(" ", arguments.Where(a => a != null));
            }
            psi.WorkingDirectory = workingDirectory;
            psi.CreateNoWindow = !visible;
            psi.UseShellExecute = false;
            psi.RedirectStandardError = !visible || (redirector != null);
            psi.RedirectStandardOutput = !visible || (redirector != null);
            psi.RedirectStandardInput = !visible;
            psi.StandardOutputEncoding = outputEncoding ?? psi.StandardOutputEncoding;
            psi.StandardErrorEncoding = errorEncoding ?? outputEncoding ?? psi.StandardErrorEncoding;
            if (env != null) {
                foreach (var kv in env) {
                    psi.EnvironmentVariables[kv.Key] = kv.Value;
                }
            }

            var process = new Process { StartInfo = psi };
            return new ProcessOutput(process, redirector);
        }
コード例 #17
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));
        }
コード例 #18
0
ファイル: CookiecutterClient.cs プロジェクト: zooba/PTVS
        private static async Task<ProcessOutputResult> RunPythonScript(Redirector redirector, string interpreterPath, string script, string parameters) {
            var outputLines = new List<string>();
            var errorLines = new List<string>();

            ProcessOutput output = null;
            var arguments = string.Format("\"{0}\" {1}", script, parameters);
            var listRedirector = new ListRedirector(outputLines, errorLines);
            var outerRedirector = new TeeRedirector(redirector, listRedirector);

            output = ProcessOutput.Run(interpreterPath, new string[] { arguments }, null, null, false, outerRedirector);

            var result = await WaitForOutput(interpreterPath, output);
            result.StandardOutputLines = outputLines.ToArray();
            result.StandardErrorLines = errorLines.ToArray();

            return result;
        }