MalwareMultiScan/MalwareMultiScan.Backends/Backends/Abstracts/AbstractLocalProcessScanBackend.cs
2020-10-22 09:28:28 +03:00

76 lines
2.6 KiB
C#

using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
namespace MalwareMultiScan.Backends.Backends.Abstracts
{
public abstract class AbstractLocalProcessScanBackend : AbstractScanBackend
{
private readonly ILogger _logger;
protected AbstractLocalProcessScanBackend(ILogger logger)
{
_logger = logger;
}
protected virtual Regex MatchRegex { get; }
protected virtual string BackendPath { get; }
protected virtual bool ParseStdErr { get; }
protected virtual bool ThrowOnNonZeroExitCode { get; } = true;
protected virtual string GetBackendArguments(string path)
{
throw new NotImplementedException();
}
public override async Task<string[]> ScanAsync(string path, CancellationToken cancellationToken)
{
var process = new Process
{
StartInfo = new ProcessStartInfo(BackendPath, GetBackendArguments(path))
{
RedirectStandardError = true,
RedirectStandardOutput = true,
WorkingDirectory = Path.GetDirectoryName(BackendPath) ?? Directory.GetCurrentDirectory()
}
};
_logger.LogInformation(
$"Starting process {process.StartInfo.FileName} " +
$"with arguments {process.StartInfo.Arguments} " +
$"in working directory {process.StartInfo.WorkingDirectory}");
process.Start();
cancellationToken.Register(() =>
{
if (!process.HasExited)
process.Kill(true);
});
process.WaitForExit();
_logger.LogInformation($"Process has exited with code {process.ExitCode}");
var standardOutput = await process.StandardOutput.ReadToEndAsync();
var standardError = await process.StandardError.ReadToEndAsync();
_logger.LogDebug($"Process standard output: {standardOutput}");
_logger.LogDebug($"Process standard error: {standardError}");
if (ThrowOnNonZeroExitCode && process.ExitCode != 0)
throw new ApplicationException($"Process has terminated with an exit code {process.ExitCode}");
return MatchRegex
.Matches(ParseStdErr ? standardError : standardOutput)
.Where(x => x.Success)
.Select(x => x.Groups["threat"].Value)
.ToArray();
}
}
}