From 58a392ff053dc9ca846440a3cc4a3bb86cbe1bae Mon Sep 17 00:00:00 2001 From: Ben Olden-Cooligan Date: Mon, 2 Sep 2024 15:35:45 -0700 Subject: [PATCH] Fix console cancellation #423 #393 --- NAPS2.Lib/Automation/AutomatedScanning.cs | 26 ++++++++++++++----- .../ConsoleResources.Designer.cs | 9 +++++++ .../ConsoleResources/ConsoleResources.resx | 3 +++ .../Internal/Twain/RemoteTwainController.cs | 3 +++ 4 files changed, 35 insertions(+), 6 deletions(-) diff --git a/NAPS2.Lib/Automation/AutomatedScanning.cs b/NAPS2.Lib/Automation/AutomatedScanning.cs index 6723b58385..736873735f 100644 --- a/NAPS2.Lib/Automation/AutomatedScanning.cs +++ b/NAPS2.Lib/Automation/AutomatedScanning.cs @@ -33,6 +33,7 @@ internal class AutomatedScanning private readonly ConsoleOutput _output; private readonly AutomatedScanningOptions _options; + private readonly CancellationTokenSource _cts = new(); private PdfEncryption _parsedEncryptConfigOption = null!; private List> _scanList = null!; private int _pagesScanned; @@ -78,6 +79,15 @@ private void OutputVerbose(string value, params object[] args) public async Task Execute() { + Console.CancelKeyPress += (_, e) => + { + if (!_cts.IsCancellationRequested) + { + Console.WriteLine(ConsoleResources.Cancelling); + _cts.Cancel(); + e.Cancel = true; + } + }; bool hasUnexpectedException = false; try { @@ -115,6 +125,8 @@ public async Task Execute() await ImportImages(); } + if (_cts.IsCancellationRequested) return; + ConfigureOcr(); if (_options.Number > 0) @@ -130,6 +142,8 @@ public async Task Execute() await PerformScan(profile); } + if (_cts.IsCancellationRequested) return; + ReorderScannedImages(); if (_options.OutputPath != null) @@ -245,9 +259,7 @@ private async Task ListDevices() }; await SetProfileOverrides(profile); - var cts = new CancellationTokenSource(); - Console.CancelKeyPress += (_, _) => cts.Cancel(); - await foreach (var device in _scanPerformer.GetDevices(profile, cts.Token)) + await foreach (var device in _scanPerformer.GetDevices(profile, _cts.Token)) { _output.Writer.WriteLine(device.Name); } @@ -332,7 +344,7 @@ private async Task ImportImages() PatchTOnly = true } }; - await foreach (var image in _fileImporter.Import(actualPath, importParams)) + await foreach (var image in _fileImporter.Import(actualPath, importParams, _cts.Token)) { scan.Add(PostProcessImportedImage(image)); } @@ -443,7 +455,7 @@ private async Task EmailScannedImages() } OutputVerbose(ConsoleResources.SendingEmail); - if (await _emailProviderFactory.Default.SendEmail(message)) + if (await _emailProviderFactory.Default.SendEmail(message, _cts.Token)) { OutputVerbose(ConsoleResources.EmailSent); } @@ -590,6 +602,7 @@ private async Task DoExportToImageFiles(string outputPath) foreach (var scan in _scanList) { var op = _operationFactory.Create(); + _cts.Token.Register(op.Cancel); int i = -1; op.StatusChanged += (sender, args) => { @@ -673,6 +686,7 @@ private async Task DoExportToPdf(string path, bool email) foreach (var fileContents in _scanList) { var op = _operationFactory.Create(); + _cts.Token.Register(op.Cancel); int i = -1; op.StatusChanged += (sender, args) => { @@ -731,7 +745,7 @@ private async Task PerformScan(ScanProfile profile) DetectPatchT = _options.SplitPatchT, OcrParams = _ocrParams }; - await foreach (var image in _scanPerformer.PerformScan(profile, scanParams)) + await foreach (var image in _scanPerformer.PerformScan(profile, scanParams, cancelToken: _cts.Token)) { ReceiveScannedImage(image); } diff --git a/NAPS2.Lib/Lang/ConsoleResources/ConsoleResources.Designer.cs b/NAPS2.Lib/Lang/ConsoleResources/ConsoleResources.Designer.cs index bbb2e70156..d579fb411a 100644 --- a/NAPS2.Lib/Lang/ConsoleResources/ConsoleResources.Designer.cs +++ b/NAPS2.Lib/Lang/ConsoleResources/ConsoleResources.Designer.cs @@ -104,6 +104,15 @@ internal static string BeginningScan { } } + /// + /// Looks up a localized string similar to Cancelling... Press Ctrl+C again to terminate.. + /// + internal static string Cancelling { + get { + return ResourceManager.GetString("Cancelling", resourceCulture); + } + } + /// /// Looks up a localized string similar to The specified component is already installed.. /// diff --git a/NAPS2.Lib/Lang/ConsoleResources/ConsoleResources.resx b/NAPS2.Lib/Lang/ConsoleResources/ConsoleResources.resx index 3e3d02d4d6..27d324d60d 100644 --- a/NAPS2.Lib/Lang/ConsoleResources/ConsoleResources.resx +++ b/NAPS2.Lib/Lang/ConsoleResources/ConsoleResources.resx @@ -263,4 +263,7 @@ Use the "--importpassword" option. The --driver option must be set to use the --device or --listdevices option. Possible values: {0} + + Cancelling... Press Ctrl+C again to terminate. + \ No newline at end of file diff --git a/NAPS2.Sdk/Scan/Internal/Twain/RemoteTwainController.cs b/NAPS2.Sdk/Scan/Internal/Twain/RemoteTwainController.cs index f4488129d0..586bbe007f 100644 --- a/NAPS2.Sdk/Scan/Internal/Twain/RemoteTwainController.cs +++ b/NAPS2.Sdk/Scan/Internal/Twain/RemoteTwainController.cs @@ -37,6 +37,9 @@ public async Task StartScan(ScanOptions options, ITwainEvents twainEvents, Cance // We need to report cancellation so that TwainImageProcessor doesn't return a partial image _scanningContext.Logger.LogDebug("NAPS2.TW - Sending cancel event"); twainEvents.TransferCanceled(new TwainTransferCanceled()); + // We also want to wait until the worker closes so we guarantee the parent process doesn't die before the + // TWAIN process has a chance to clean up + await workerContext.Stop(); } }