104 строки
3.2 KiB
C#
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));
|
|
}
|
|
}
|
|
}
|