mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
Refactor process starting and stdout and stderr reading
This commit is contained in:
@@ -187,12 +187,12 @@ namespace Semmle.Autobuild.Shared
|
||||
|
||||
bool IBuildActions.FileExists(string file) => File.Exists(file);
|
||||
|
||||
private static ProcessStartInfo GetProcessStartInfo(string exe, string arguments, string? workingDirectory, IDictionary<string, string>? environment, bool redirectStandardOutput)
|
||||
private static ProcessStartInfo GetProcessStartInfo(string exe, string arguments, string? workingDirectory, IDictionary<string, string>? environment)
|
||||
{
|
||||
var pi = new ProcessStartInfo(exe, arguments)
|
||||
{
|
||||
UseShellExecute = false,
|
||||
RedirectStandardOutput = redirectStandardOutput
|
||||
RedirectStandardOutput = true
|
||||
};
|
||||
if (workingDirectory is not null)
|
||||
pi.WorkingDirectory = workingDirectory;
|
||||
@@ -204,40 +204,22 @@ namespace Semmle.Autobuild.Shared
|
||||
|
||||
int IBuildActions.RunProcess(string exe, string args, string? workingDirectory, System.Collections.Generic.IDictionary<string, string>? env, BuildOutputHandler onOutput, BuildOutputHandler onError)
|
||||
{
|
||||
var pi = GetProcessStartInfo(exe, args, workingDirectory, env, true);
|
||||
using var p = new Process
|
||||
{
|
||||
StartInfo = pi
|
||||
};
|
||||
p.StartInfo.RedirectStandardError = true;
|
||||
p.OutputDataReceived += new DataReceivedEventHandler((sender, e) => onOutput(e.Data));
|
||||
p.ErrorDataReceived += new DataReceivedEventHandler((sender, e) => onError(e.Data));
|
||||
var pi = GetProcessStartInfo(exe, args, workingDirectory, env);
|
||||
pi.RedirectStandardError = true;
|
||||
|
||||
p.Start();
|
||||
|
||||
p.BeginErrorReadLine();
|
||||
p.BeginOutputReadLine();
|
||||
|
||||
p.WaitForExit();
|
||||
return p.ExitCode;
|
||||
return pi.ReadOutput(out _, onOut: s => onOutput(s), onError: s => onError(s));
|
||||
}
|
||||
|
||||
int IBuildActions.RunProcess(string cmd, string args, string? workingDirectory, IDictionary<string, string>? environment)
|
||||
{
|
||||
var pi = GetProcessStartInfo(cmd, args, workingDirectory, environment, false);
|
||||
using var p = Process.Start(pi);
|
||||
if (p is null)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
p.WaitForExit();
|
||||
return p.ExitCode;
|
||||
var pi = GetProcessStartInfo(cmd, args, workingDirectory, environment);
|
||||
return pi.ReadOutput(out _, onOut: Console.WriteLine, onError: null);
|
||||
}
|
||||
|
||||
int IBuildActions.RunProcess(string cmd, string args, string? workingDirectory, IDictionary<string, string>? environment, out IList<string> stdOut)
|
||||
{
|
||||
var pi = GetProcessStartInfo(cmd, args, workingDirectory, environment, true);
|
||||
return pi.ReadOutput(out stdOut, printToConsole: false);
|
||||
var pi = GetProcessStartInfo(cmd, args, workingDirectory, environment);
|
||||
return pi.ReadOutput(out stdOut, onOut: null, onError: null);
|
||||
}
|
||||
|
||||
void IBuildActions.DirectoryDelete(string dir, bool recursive) => Directory.Delete(dir, recursive);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using Semmle.Util;
|
||||
@@ -24,7 +25,8 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
var startInfo = new ProcessStartInfo(Exec, args)
|
||||
{
|
||||
UseShellExecute = false,
|
||||
RedirectStandardOutput = true
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true
|
||||
};
|
||||
// Set the .NET CLI language to English to avoid localized output.
|
||||
startInfo.EnvironmentVariables["DOTNET_CLI_UI_LANGUAGE"] = "en";
|
||||
@@ -35,7 +37,16 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
{
|
||||
progressMonitor.RunningProcess($"{Exec} {args}");
|
||||
var pi = MakeDotnetStartInfo(args);
|
||||
var exitCode = pi.ReadOutput(out output, true);
|
||||
var threadId = $"[{Environment.CurrentManagedThreadId:D3}]";
|
||||
void onOut(string s)
|
||||
{
|
||||
Console.Out.WriteLine($"{threadId} {s}");
|
||||
}
|
||||
void onError(string s)
|
||||
{
|
||||
Console.Error.WriteLine($"{threadId} {s}");
|
||||
}
|
||||
var exitCode = pi.ReadOutput(out output, onOut, onError);
|
||||
if (exitCode != 0)
|
||||
{
|
||||
progressMonitor.CommandFailed(Exec, args, exitCode);
|
||||
|
||||
@@ -8,38 +8,56 @@ namespace Semmle.Util
|
||||
{
|
||||
/// <summary>
|
||||
/// Runs this process, and returns the exit code, as well as the contents
|
||||
/// of stdout in <paramref name="stdout"/>. If <paramref name="printToConsole"/>
|
||||
/// is true, then stdout is printed to the console and each line is prefixed
|
||||
/// with the thread id.
|
||||
/// of stdout in <paramref name="stdout"/>.
|
||||
/// </summary>
|
||||
public static int ReadOutput(this ProcessStartInfo pi, out IList<string> stdout, bool printToConsole)
|
||||
public static int ReadOutput(this ProcessStartInfo pi, out IList<string> stdout, Action<string>? onOut, Action<string>? onError)
|
||||
{
|
||||
stdout = new List<string>();
|
||||
using var process = Process.Start(pi);
|
||||
|
||||
if (process is null)
|
||||
var @out = new List<string>();
|
||||
using var process = new Process
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
StartInfo = pi
|
||||
};
|
||||
|
||||
if (pi.RedirectStandardOutput && !pi.UseShellExecute)
|
||||
if (process.StartInfo.RedirectStandardOutput && !pi.UseShellExecute)
|
||||
{
|
||||
string? s;
|
||||
do
|
||||
process.OutputDataReceived += new DataReceivedEventHandler((sender, e) =>
|
||||
{
|
||||
s = process.StandardOutput.ReadLine();
|
||||
if (s is not null)
|
||||
if (e.Data == null)
|
||||
{
|
||||
if (printToConsole)
|
||||
{
|
||||
Console.WriteLine($"[{Environment.CurrentManagedThreadId:D3}] {s}");
|
||||
}
|
||||
stdout.Add(s);
|
||||
return;
|
||||
}
|
||||
}
|
||||
while (s is not null);
|
||||
|
||||
onOut?.Invoke(e.Data);
|
||||
@out.Add(e.Data);
|
||||
});
|
||||
}
|
||||
if (process.StartInfo.RedirectStandardError && !pi.UseShellExecute)
|
||||
{
|
||||
process.ErrorDataReceived += new DataReceivedEventHandler((sender, e) =>
|
||||
{
|
||||
if (e.Data == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
onError?.Invoke(e.Data);
|
||||
});
|
||||
}
|
||||
|
||||
process.Start();
|
||||
|
||||
if (process.StartInfo.RedirectStandardError)
|
||||
{
|
||||
process.BeginErrorReadLine();
|
||||
}
|
||||
|
||||
if (process.StartInfo.RedirectStandardOutput)
|
||||
{
|
||||
process.BeginOutputReadLine();
|
||||
}
|
||||
|
||||
process.WaitForExit();
|
||||
stdout = @out;
|
||||
return process.ExitCode;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user