using System; using System.Linq; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using MalwareMultiScan.Backends.Services.Interfaces; namespace MalwareMultiScan.Backends.Backends.Abstracts { /// public abstract class AbstractLocalProcessScanBackend : AbstractScanBackend { private readonly IProcessRunner _processRunner; /// protected AbstractLocalProcessScanBackend(IProcessRunner processRunner) { _processRunner = processRunner; } /// /// Regex to extract names of threats. /// protected abstract Regex MatchRegex { get; } /// /// Path to the backend. /// protected abstract string BackendPath { get; } /// /// Parse StdErr instead of StdOut. /// protected virtual bool ParseStdErr { get; } = false; /// /// Throw on non-zero exit code. /// protected virtual bool ThrowOnNonZeroExitCode { get; } = true; /// /// Get backend process parameters. /// /// Path to the temporary file. /// Formatted string with parameters and path. protected abstract string GetBackendArguments(string path); /// public override Task ScanAsync(string path, CancellationToken cancellationToken) { var exitCode = _processRunner.RunTillCompletion(BackendPath, GetBackendArguments(path), cancellationToken, out var standardOutput, out var standardError); if (ThrowOnNonZeroExitCode && exitCode != 0) throw new ApplicationException($"Process has terminated with an exit code {exitCode}"); return Task.FromResult(MatchRegex .Matches(ParseStdErr ? standardError : standardOutput) .Where(x => x.Success) .Select(x => x.Groups["threat"].Value) .ToArray()); } } }