private void WriteError(string message) { if (_output != null) { _output.WriteErrorLine(message); } }
private async Task <bool> DownloadTypings(IEnumerable <string> packages, Redirector redirector) { if (!packages.Any()) { return(true); } string tsdPath = await EnsureTsdInstalled(); if (string.IsNullOrEmpty(tsdPath)) { if (redirector != null) { redirector.WriteErrorLine(SR.GetString(SR.TsdNotInstalledError)); } return(false); } using (var process = ProcessOutput.Run( tsdPath, TsdInstallArguments(packages), _pathToRootProjectDirectory, null, false, redirector, quoteArgs: true)) { if (!process.IsStarted) { // Process failed to start, and any exception message has // already been sent through the redirector if (redirector != null) { redirector.WriteErrorLine("could not start tsd"); } return(false); } var i = await process; if (i == 0) { if (redirector != null) { redirector.WriteLine(SR.GetString(SR.TsdInstallCompleted)); } return(true); } else { process.Kill(); if (redirector != null) { redirector.WriteErrorLine(SR.GetString(SR.TsdInstallErrorOccurred)); } return(false); } } }
// TODO: This is duplicated from Npm project // We should integrate this into the NpmCommander internal static async Task <IEnumerable <string> > ExecuteNpmCommandAsync( string pathToNpm, string executionDirectory, string[] arguments, bool visible = false, Redirector redirector = null) { IEnumerable <string> standardOutputLines = null; using (var process = ProcessOutput.Run( pathToNpm, arguments, executionDirectory, /*env*/ null, visible, redirector, quoteArgs: false, outputEncoding: redirector == null ? null : Encoding.UTF8)) { var whnd = process.WaitHandle; if (whnd == null) { // Process failed to start, and any exception message has // already been sent through the redirector redirector?.WriteErrorLine("Error - cannot start npm"); } else { var finished = await Task.Run(() => whnd.WaitOne()); if (finished) { Debug.Assert(process.ExitCode.HasValue, "npm process has not really exited"); // there seems to be a case when we're signalled as completed, but the // process hasn't actually exited process.Wait(); if (process.StandardOutputLines != null) { standardOutputLines = process.StandardOutputLines.ToList(); } } else { process.Kill(); redirector?.WriteErrorLine("\r\n==== npm command cancelled ====\r\n\r\n"); throw new OperationCanceledException(); } } } return(standardOutputLines); }
private static async Task <bool> CompileAsync(string arguments, string workingDir, Redirector redirector) { Debug.Assert(!string.IsNullOrEmpty(arguments), $"{nameof(arguments)} should not be empty."); var pathToTsc = Path.Combine(TypeScriptCompilerLocator.GetDefaultVersion(), CompilerExe); redirector?.WriteLine($"=== {Resources.TscBuildStarted}: {pathToTsc} {arguments} ==="); using (var process = ProcessOutput.Run( pathToTsc, new[] { arguments }, workingDir, env: null, visible: false, redirector: redirector, quoteArgs: false, outputEncoding: Encoding.UTF8)) { var whnd = process.WaitHandle; if (whnd == null) { // Process failed to start, and any exception message has // already been sent through the redirector redirector.WriteErrorLine(string.Format(Resources.TscBuildError, pathToTsc)); return(false); } else { var finished = await Task.Run(() => whnd.WaitOne()); if (finished) { Debug.Assert(process.ExitCode.HasValue, "tsc.exe process has not really exited"); // there seems to be a case when we're signalled as completed, but the // process hasn't actually exited process.Wait(); redirector.WriteErrorLine($"==== {Resources.TscBuildCompleted} ===="); return(process.ExitCode == 0); } else { process.Kill(); redirector.WriteErrorLine($"==== {Resources.TscBuildCanceled} ===="); return(false); } } } }
public async Task DeleteTemplateAsync(TemplateViewModel template) { try { string remote = template.RemoteUrl; _outputWindow.ShowAndActivate(); _outputWindow.WriteLine(String.Empty); _outputWindow.WriteLine(Strings.DeletingTemplateStarted.FormatUI(template.ClonedPath)); await _installedSource.DeleteTemplateAsync(template.ClonedPath); _outputWindow.WriteLine(Strings.DeletingTemplateSuccess.FormatUI(template.ClonedPath)); ReportTemplateEvent(CookiecutterTelemetry.TelemetryArea.Template, CookiecutterTelemetry.TemplateEvents.Delete, template); if (!string.IsNullOrEmpty(remote)) { var t = Installed.Templates.SingleOrDefault(current => (current as TemplateViewModel)?.RemoteUrl == remote) as TemplateViewModel; if (t != null) { Installed.Templates.Remove(t); } t = Recommended.Templates.SingleOrDefault(current => (current as TemplateViewModel)?.RemoteUrl == remote) as TemplateViewModel; if (t != null) { t.ClonedPath = string.Empty; } t = GitHub.Templates.SingleOrDefault(current => (current as TemplateViewModel)?.RemoteUrl == remote) as TemplateViewModel; if (t != null) { t.ClonedPath = string.Empty; } } else { if (Installed.Templates.Contains(template)) { Installed.Templates.Remove(template); } } } catch (Exception ex) when(!ex.IsCriticalException()) { _outputWindow.WriteErrorLine(ex.Message); _outputWindow.WriteLine(Strings.DeletingTemplateFailed.FormatUI(template.ClonedPath)); ReportTemplateEvent(CookiecutterTelemetry.TelemetryArea.Template, CookiecutterTelemetry.TemplateEvents.Delete, template, ex); } }
private void WriteError(string resourceKey, params object[] args) { if (_output != null) { _output.WriteErrorLine(SR.GetString(resourceKey, args)); } }
public Task DeleteTemplateAsync(TemplateViewModel template) { try { string remote = template.RemoteUrl; _outputWindow.WriteLine(string.Format(CultureInfo.CurrentUICulture, Strings.DeletingTemplateStarted, template.ClonedPath)); ShellUtils.DeleteDirectory(template.ClonedPath); _outputWindow.WriteLine(string.Empty); _outputWindow.WriteLine(string.Format(CultureInfo.CurrentUICulture, Strings.DeletingTemplateSuccess, template.ClonedPath)); _outputWindow.ShowAndActivate(); if (!string.IsNullOrEmpty(remote)) { var t = Installed.Templates.SingleOrDefault(current => (current as TemplateViewModel)?.RemoteUrl == remote) as TemplateViewModel; if (t != null) { Installed.Templates.Remove(t); } t = Recommended.Templates.SingleOrDefault(current => (current as TemplateViewModel)?.RemoteUrl == remote) as TemplateViewModel; if (t != null) { t.ClonedPath = string.Empty; } t = GitHub.Templates.SingleOrDefault(current => (current as TemplateViewModel)?.RemoteUrl == remote) as TemplateViewModel; if (t != null) { t.ClonedPath = string.Empty; } } else { if (Installed.Templates.Contains(template)) { Installed.Templates.Remove(template); } } } catch (Exception ex) when(!ex.IsCriticalException()) { _outputWindow.WriteErrorLine(ex.Message); _outputWindow.WriteLine(string.Empty); _outputWindow.WriteLine(string.Format(CultureInfo.CurrentUICulture, Strings.DeletingTemplateFailed, template.ClonedPath)); _outputWindow.ShowAndActivate(); } return(Task.CompletedTask); }
private async Task <bool> ExecuteTypingsTool(IEnumerable <string> arguments, Redirector redirector) { string typingsTool = await EnsureTypingsToolInstalled(redirector); if (string.IsNullOrEmpty(typingsTool)) { redirector?.WriteErrorLine(Resources.TypingsToolNotInstalledError); return(false); } using (var process = ProcessOutput.Run( typingsTool, arguments, _pathToRootProjectDirectory, null, false, redirector, quoteArgs: true, outputEncoding: Encoding.UTF8, errorEncoding: Encoding.UTF8)) { if (!process.IsStarted) { // Process failed to start, and any exception message has // already been sent through the redirector redirector?.WriteErrorLine(Resources.TypingsToolCouldNotStart); return(false); } var i = await process; if (i == 0) { redirector?.WriteLine(Resources.TypingsToolTypingsInstallCompleted); return(true); } else { process.Kill(); redirector?.WriteErrorLine(Resources.TypingsToolTypingsInstallErrorOccurred); return(false); } } }
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); }
private async Task <string> EnsureTypingsToolInstalled(Redirector redirector) { if (File.Exists(TypingsToolPath)) { return(TypingsToolPath); } if (_didTryToInstallTypingsTool) { return(null); } if (!await InstallTypingsTool()) { redirector?.WriteErrorLine(Resources.TypingsToolInstallFailed); return(null); } return(await EnsureTypingsToolInstalled(redirector)); }
/// <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)); } }
/// <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(Path.Combine(Environment.SystemDirectory, "cmd.exe")) { CreateNoWindow = true, WindowStyle = ProcessWindowStyle.Hidden, UseShellExecute = true, 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) { if (IsCriticalException(ex)) { throw; } 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) { if (IsCriticalException(ex)) { throw; } 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); }
public void OnErrorTextReceived(IPackageManager sender, string text) { _outputWindow.WriteErrorLine(text.TrimEndNewline()); }
private void PipExtensionProvider_ErrorTextReceived(object sender, OutputEventArgs e) { _outputWindow.WriteErrorLine(e.Data.TrimEndNewline()); }
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 } } } }
/// <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)); }
private void InvalidUrl(string url) { _redirector.WriteErrorLine(Strings.CookiecutterClient_Invalidurl.FormatUI(url)); }
private void WrongJsonType(string name, JTokenType expected, JTokenType actual) { _redirector.WriteErrorLine(string.Format("'{0}' from _visual_studio section in context file should be of type '{1}', instead of '{2}'.", name, expected, actual)); }
public void OnErrorTextReceived(string text) { _outputWindow.WriteErrorLine(text.TrimEndNewline()); }
public void OnErrorTextReceived(ICondaEnvironmentManager sender, string text) { _window.WriteErrorLine(text.TrimEndNewline()); }
private void InvalidUrl(string url) { _redirector.WriteErrorLine(string.Format("'{0}' from _visual_studio section in context file should be an absolute http or https url.", url)); }
private static DateTime? TryGetLastWriteTimeUtc(string path, Redirector output = null) { try { return File.GetLastWriteTimeUtc(path); } catch (UnauthorizedAccessException ex) { if (output != null) { output.WriteErrorLine(string.Format("Failed to access {0}: {1}", path, ex.Message)); #if DEBUG output.WriteErrorLine(ex.ToString()); #endif } } catch (ArgumentException ex) { if (output != null) { output.WriteErrorLine(string.Format("Failed to access {0}: {1}", path, ex.Message)); #if DEBUG output.WriteErrorLine(ex.ToString()); #endif } } catch (PathTooLongException ex) { if (output != null) { output.WriteErrorLine(string.Format("Failed to access {0}: {1}", path, ex.Message)); #if DEBUG output.WriteErrorLine(ex.ToString()); #endif } } catch (NotSupportedException ex) { if (output != null) { output.WriteErrorLine(string.Format("Failed to access {0}: {1}", path, ex.Message)); #if DEBUG output.WriteErrorLine(ex.ToString()); #endif } } return null; }
private void PipExtensionProvider_ErrorTextReceived(object sender, ValueEventArgs <string> e) { _outputWindow.WriteErrorLine(e.Value); }
private async Task ReanalyzeWorkspaceHelperAsync(IPythonInterpreterFactory factory, Redirector log) { _site.MustBeCalledFromUIThread(); try { if (!_recreatingAnalyzer.Wait(0)) { // Someone else is recreating, so wait for them to finish and return log?.WriteLine("Waiting for existing call"); await _recreatingAnalyzer.WaitAsync(); try { log?.WriteLine("Existing call complete"); } catch { _recreatingAnalyzer.Release(); throw; } if (_analyzer?.InterpreterFactory == factory) { _recreatingAnalyzer.Release(); return; } } } catch (ObjectDisposedException) { return; } IVsStatusbar statusBar = null; bool statusBarConfigured = false; try { if ((statusBar = _site.GetService(typeof(SVsStatusbar)) as IVsStatusbar) != null) { statusBar.SetText(Strings.AnalyzingProject); try { object index = (short)0; statusBar.Animation(1, ref index); } catch (ArgumentNullException) { // Issue in status bar implementation // https://github.com/Microsoft/PTVS/issues/3064 // Silently suppress since animation is not critical. } statusBar.FreezeOutput(1); statusBarConfigured = true; } var oldWatcher = _workspaceFileWatcher; _workspaceFileWatcher = new FileWatcher(_pythonWorkspace.Location) { EnableRaisingEvents = true, IncludeSubdirectories = true, NotifyFilter = NotifyFilters.FileName | NotifyFilters.LastWrite }; _workspaceFileWatcher.Changed += OnWorkspaceFileChanged; _workspaceFileWatcher.Deleted += OnWorkspaceFileDeleted; oldWatcher?.Dispose(); log?.WriteLine("Creating new workspace analyzer"); var analyzer = await CreateAnalyzerAsync(factory, _pythonWorkspace.Location); Debug.Assert(analyzer != null); log?.WriteLine($"Created workspace analyzer {analyzer}"); WorkspaceAnalyzerChanging?.Invoke(this, new AnalyzerChangingEventArgs(_analyzer, analyzer)); var oldAnalyzer = Interlocked.Exchange(ref _analyzer, analyzer); if (oldAnalyzer != null) { if (analyzer != null) { int beforeCount = analyzer.Files.Count(); log?.WriteLine($"Transferring from old analyzer {oldAnalyzer}, which has {oldAnalyzer.Files.Count()} files"); await analyzer.TransferFromOldAnalyzer(oldAnalyzer); log?.WriteLine($"Tranferred {analyzer.Files.Count() - beforeCount} files"); log?.WriteLine($"Old analyzer now has {oldAnalyzer.Files.Count()} files"); } if (oldAnalyzer.RemoveUser()) { log?.WriteLine("Disposing old analyzer"); oldAnalyzer.Dispose(); } } var files = new List <string>(); var pythonServices = _site.GetPythonToolsService(); foreach (var existing in pythonServices.GetActiveSharedAnalyzers().Select(kv => kv.Value).Where(v => !v.IsDisposed)) { foreach (var kv in existing.LoadedFiles) { files.Add(kv.Key); log?.WriteLine($"Unloading {kv.Key} from default analyzer"); foreach (var b in (kv.Value.TryGetBufferParser()?.AllBuffers).MaybeEnumerate()) { PythonTextBufferInfo.MarkForReplacement(b); } try { await existing.UnloadFileAsync(kv.Value); } catch (ObjectDisposedException) { break; } } } if (analyzer != null) { // Set search paths first, as it will save full reanalysis later log?.WriteLine("Setting search paths"); await analyzer.SetSearchPathsAsync(_pythonWorkspace.GetAbsoluteSearchPaths()); // Add all our files into our analyzer log?.WriteLine($"Adding {files.Count} files"); await analyzer.AnalyzeFileAsync(files.ToArray()); } WorkspaceAnalyzerChanged?.Invoke(this, EventArgs.Empty); } catch (ObjectDisposedException) { // Raced with disposal } catch (Exception ex) { log?.WriteErrorLine(ex.ToString()); throw; } finally { try { if (statusBar != null && statusBarConfigured) { statusBar.FreezeOutput(0); object index = (short)0; statusBar.Animation(0, ref index); statusBar.Clear(); } } finally { try { _recreatingAnalyzer.Release(); } catch (ObjectDisposedException) { } } } }
private void WriteError(string message) { _output?.WriteErrorLine(message); }
internal static async Task <IEnumerable <string> > ExecuteNpmCommandAsync( Redirector redirector, string pathToNpm, string executionDirectory, string[] arguments, ManualResetEvent cancellationResetEvent) { IEnumerable <string> standardOutputLines = null; using (var process = ProcessOutput.Run( pathToNpm, arguments, executionDirectory, null, false, redirector, quoteArgs: false, outputEncoding: Encoding.UTF8 // npm uses UTF-8 regardless of locale if its output is redirected )) { var whnd = process.WaitHandle; if (whnd == null) { // Process failed to start, and any exception message has // already been sent through the redirector if (redirector != null) { redirector.WriteErrorLine(Resources.ErrCannotStartNpm); } } else { var handles = cancellationResetEvent != null ? new[] { whnd, cancellationResetEvent } : new[] { whnd }; var i = await Task.Run(() => WaitHandle.WaitAny(handles)); if (i == 0) { Debug.Assert(process.ExitCode.HasValue, "npm process has not really exited"); process.Wait(); if (process.StandardOutputLines != null) { standardOutputLines = process.StandardOutputLines.ToList(); } if (redirector != null) { redirector.WriteLine(string.Format(CultureInfo.InvariantCulture, "\r\n===={0}====\r\n\r\n", string.Format(CultureInfo.InvariantCulture, Resources.NpmCommandCompletedWithExitCode, process.ExitCode ?? -1) )); } } else { process.Kill(); if (redirector != null) { redirector.WriteErrorLine(string.Format(CultureInfo.InvariantCulture, "\r\n===={0}====\r\n\r\n", Resources.NpmCommandCancelled)); } if (cancellationResetEvent != null) { cancellationResetEvent.Reset(); } throw new OperationCanceledException(); } } } return(standardOutputLines); }
public void OnErrorTextReceived(string text) { _outputWindow.WriteErrorLine(RemoveLastNewline(text)); }