xamarin-macios/tools/common/Execution.cs

104 строки
3.2 KiB
C#

/*
* Copyright 2014 Xamarin Inc. All rights reserved.
* Copyright 2019 Microsoft Corp. All rights reserved.
*
* Authors:
* Rolf Bjarne Kvinge <rolf@xamarin.com>
*
*/
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Xamarin.Utils;
namespace Xamarin.Bundler {
public partial class Driver {
public static int RunCommand (string path, IList<string> args, string [] env, out StringBuilder output, bool suppressPrintOnErrors, int verbose)
{
output = new StringBuilder ();
return RunCommand (path, StringUtils.FormatArguments (args), env, output, suppressPrintOnErrors, verbose);
}
public static int RunCommand (string path, IList<string> args, string [] env, StringBuilder output, bool suppressPrintOnErrors, int verbose)
{
return RunCommand (path, StringUtils.FormatArguments (args), env, output, suppressPrintOnErrors, verbose);
}
static int RunCommand (string path, string args, string[] env, StringBuilder output, bool suppressPrintOnErrors, int verbose)
{
var info = new ProcessStartInfo (path, args);
info.UseShellExecute = false;
info.RedirectStandardInput = false;
info.RedirectStandardOutput = true;
info.RedirectStandardError = true;
var stdout_completed = new ManualResetEvent (false);
var stderr_completed = new ManualResetEvent (false);
if (output == null)
output = new StringBuilder ();
if (env != null){
if (env.Length % 2 != 0)
throw new Exception ("You passed an environment key without a value");
for (int i = 0; i < env.Length; i+= 2)
info.EnvironmentVariables [env[i]] = env[i+1];
}
if (verbose > 0)
Console.WriteLine ("{0} {1}", path, args);
using (var p = Process.Start (info)) {
p.OutputDataReceived += (s, e) => {
if (e.Data != null) {
lock (output)
output.AppendLine (e.Data);
} else {
stdout_completed.Set ();
}
};
p.ErrorDataReceived += (s, e) => {
if (e.Data != null) {
lock (output)
output.AppendLine (e.Data);
} else {
stderr_completed.Set ();
}
};
p.BeginOutputReadLine ();
p.BeginErrorReadLine ();
p.WaitForExit ();
stderr_completed.WaitOne (TimeSpan.FromSeconds (1));
stdout_completed.WaitOne (TimeSpan.FromSeconds (1));
if (p.ExitCode != 0) {
// note: this repeat the failing command line. However we can't avoid this since we're often
// running commands in parallel (so the last one printed might not be the one failing)
if (!suppressPrintOnErrors)
Console.Error.WriteLine ("Process exited with code {0}, command:\n{1} {2}{3}", p.ExitCode, path, args, output.Length > 0 ? "\n" + output.ToString () : string.Empty);
return p.ExitCode;
} else if (verbose > 0 && output.Length > 0 && !suppressPrintOnErrors) {
Console.WriteLine (output.ToString ());
}
}
return 0;
}
public static Task<int> RunCommandAsync (string path, string args, string [] env, StringBuilder output, bool suppressPrintOnErrors, int verbose)
{
return Task.Run (() => RunCommand (path, args, env, output, suppressPrintOnErrors, verbose));
}
}
}