From b603dd7f59d066c7a9afdfad57a4b6a6a059c2e1 Mon Sep 17 00:00:00 2001 From: Eugene Wang Date: Sat, 20 Feb 2016 06:50:11 -0500 Subject: [PATCH] Should now catch error before first transfer and during transfer loop as a possible #57 fix. --- src/NTwain/ITwainSession.cs | 9 ++ src/NTwain/Internals/TransferLogic.cs | 196 ++++++++++++++++---------- src/NTwain/Properties/VersionInfo.cs | 2 +- src/NTwain/TwainSession.cs | 9 ++ 4 files changed, 143 insertions(+), 73 deletions(-) diff --git a/src/NTwain/ITwainSession.cs b/src/NTwain/ITwainSession.cs index da7c88b..7547ba7 100644 --- a/src/NTwain/ITwainSession.cs +++ b/src/NTwain/ITwainSession.cs @@ -85,6 +85,15 @@ namespace NTwain /// bool IsTransferring { get; } + /// + /// Whether to stop the transfer process when transfer error is encountered. + /// May be required on some sources. + /// + /// + /// true to stop on transfer error; otherwise, false. + /// + bool StopOnTransferError { get; set; } + /// /// Try to show the built-in source selector dialog and return the selected source. /// This is not recommended and is only included for completeness. diff --git a/src/NTwain/Internals/TransferLogic.cs b/src/NTwain/Internals/TransferLogic.cs index a3a0340..e607882 100644 --- a/src/NTwain/Internals/TransferLogic.cs +++ b/src/NTwain/Internals/TransferLogic.cs @@ -45,63 +45,89 @@ namespace NTwain.Internals var pending = new TWPendingXfers(); var rc = session.DGControl.PendingXfers.Get(pending); - do + if (rc == ReturnCode.Success) { - #region raise xfer ready - - var preXferArgs = new TransferReadyEventArgs(session.CurrentSource, pending.Count, pending.EndOfJob); ; - session.SafeSyncableRaiseEvent(preXferArgs); - - #endregion - - #region actually handle xfer - - if (preXferArgs.CancelAll) + do { - rc = session.DGControl.PendingXfers.Reset(pending); - } - else - { - if (!preXferArgs.CancelCurrent) + #region raise xfer ready + + var preXferArgs = new TransferReadyEventArgs(session.CurrentSource, pending.Count, pending.EndOfJob); ; + session.SafeSyncableRaiseEvent(preXferArgs); + + #endregion + + #region actually handle xfer + + if (preXferArgs.CancelAll) { - if (xferImage) + rc = session.DGControl.PendingXfers.Reset(pending); + } + else + { + if (!preXferArgs.CancelCurrent) { - switch (imgXferMech) + if (xferImage) { - case XferMech.Memory: - DoImageMemoryXfer(session); - break; - case XferMech.File: - DoImageFileXfer(session); - break; - case XferMech.MemFile: - DoImageMemoryFileXfer(session); - break; - case XferMech.Native: - default: // always assume native - DoImageNativeXfer(session); - break; + switch (imgXferMech) + { + case XferMech.Memory: + rc = DoImageMemoryXfer(session); + break; + case XferMech.File: + rc = DoImageFileXfer(session); + break; + case XferMech.MemFile: + rc = DoImageMemoryFileXfer(session); + break; + case XferMech.Native: + default: // always assume native + rc = DoImageNativeXfer(session); + break; + } + } + if (xferAudio) + { + switch (audXferMech) + { + case XferMech.File: + rc = DoAudioFileXfer(session); + break; + case XferMech.Native: + default: // always assume native + rc = DoAudioNativeXfer(session); + break; + } } } - if (xferAudio) + + + switch (rc) { - switch (audXferMech) - { - case XferMech.File: - DoAudioFileXfer(session); - break; - case XferMech.Native: - default: // always assume native - DoAudioNativeXfer(session); - break; - } + case ReturnCode.Cancel: + default: + // as usual + rc = session.DGControl.PendingXfers.EndXfer(pending); + break; + } + + if (rc != ReturnCode.Success && session.StopOnTransferError) + { + // end xfer without setting rc to exit (good/bad?) + session.DGControl.PendingXfers.EndXfer(pending); + } + else + { + rc = session.DGControl.PendingXfers.EndXfer(pending); } } - rc = session.DGControl.PendingXfers.EndXfer(pending); - } - #endregion + #endregion - } while (rc == ReturnCode.Success && pending.Count != 0); + } while (rc == ReturnCode.Success && pending.Count != 0); + } + else + { + HandleReturnCode(session, rc); + } // some poorly written scanner drivers return failure on EndXfer so also check for pending count now. // this may break with other sources but we'll see @@ -112,15 +138,32 @@ namespace NTwain.Internals } } + private static void HandleReturnCode(ITwainSessionInternal session, ReturnCode rc) + { + switch (rc) + { + case ReturnCode.Success: + case ReturnCode.XferDone: + case ReturnCode.Cancel: + // ok to keep going + break; + default: + var status = session.CurrentSource.GetStatus(); + session.SafeSyncableRaiseEvent(new TransferErrorEventArgs(rc, status)); + break; + } + } + #region audio xfers - static void DoAudioNativeXfer(ITwainSessionInternal session) + static ReturnCode DoAudioNativeXfer(ITwainSessionInternal session) { IntPtr dataPtr = IntPtr.Zero; IntPtr lockedPtr = IntPtr.Zero; + ReturnCode xrc = ReturnCode.Failure; try { - var xrc = session.DGAudio.AudioNativeXfer.Get(ref dataPtr); + xrc = session.DGAudio.AudioNativeXfer.Get(ref dataPtr); if (xrc == ReturnCode.XferDone) { session.ChangeState(7, true); @@ -133,7 +176,7 @@ namespace NTwain.Internals } else { - session.SafeSyncableRaiseEvent(new TransferErrorEventArgs(xrc, session.CurrentSource.GetStatus())); + HandleReturnCode(session, xrc); } } catch (Exception ex) @@ -156,39 +199,43 @@ namespace NTwain.Internals dataPtr = IntPtr.Zero; } } + return xrc; } - static void DoAudioFileXfer(ITwainSessionInternal session) + static ReturnCode DoAudioFileXfer(ITwainSessionInternal session) { string filePath = null; TWSetupFileXfer setupInfo; - if (session.DGControl.SetupFileXfer.Get(out setupInfo) == ReturnCode.Success) + ReturnCode xrc = session.DGControl.SetupFileXfer.Get(out setupInfo); + if (xrc == ReturnCode.Success) { filePath = setupInfo.FileName; - } - var xrc = session.DGAudio.AudioFileXfer.Get(); - if (xrc == ReturnCode.XferDone) - { - session.SafeSyncableRaiseEvent(new DataTransferredEventArgs(session.CurrentSource, filePath, (FileFormat)0)); - } - else - { - session.SafeSyncableRaiseEvent(new TransferErrorEventArgs(xrc, session.CurrentSource.GetStatus())); + xrc = session.DGAudio.AudioFileXfer.Get(); + if (xrc == ReturnCode.XferDone) + { + session.SafeSyncableRaiseEvent(new DataTransferredEventArgs(session.CurrentSource, filePath, (FileFormat)0)); + } + else + { + HandleReturnCode(session, xrc); + } } + return xrc; } #endregion #region image xfers - static void DoImageNativeXfer(ITwainSessionInternal session) + static ReturnCode DoImageNativeXfer(ITwainSessionInternal session) { IntPtr dataPtr = IntPtr.Zero; IntPtr lockedPtr = IntPtr.Zero; + ReturnCode xrc = ReturnCode.Failure; try { - var xrc = session.DGImage.ImageNativeXfer.Get(ref dataPtr); + xrc = session.DGImage.ImageNativeXfer.Get(ref dataPtr); if (xrc == ReturnCode.XferDone) { session.ChangeState(7, true); @@ -200,7 +247,7 @@ namespace NTwain.Internals } else { - session.SafeSyncableRaiseEvent(new TransferErrorEventArgs(xrc, session.CurrentSource.GetStatus())); + HandleReturnCode(session, xrc); } } catch (Exception ex) @@ -223,9 +270,10 @@ namespace NTwain.Internals dataPtr = IntPtr.Zero; } } + return xrc; } - static void DoImageFileXfer(ITwainSessionInternal session) + static ReturnCode DoImageFileXfer(ITwainSessionInternal session) { string filePath = null; TWSetupFileXfer setupInfo; @@ -241,14 +289,16 @@ namespace NTwain.Internals } else { - session.SafeSyncableRaiseEvent(new TransferErrorEventArgs(xrc, session.CurrentSource.GetStatus())); + HandleReturnCode(session, xrc); } + return xrc; } - static void DoImageMemoryXfer(ITwainSessionInternal session) + static ReturnCode DoImageMemoryXfer(ITwainSessionInternal session) { TWSetupMemXfer memInfo; - if (session.DGControl.SetupMemXfer.Get(out memInfo) == ReturnCode.Success) + ReturnCode xrc = session.DGControl.SetupMemXfer.Get(out memInfo); + if (xrc == ReturnCode.Success) { TWImageMemXfer xferInfo = new TWImageMemXfer(); try @@ -269,7 +319,6 @@ namespace NTwain.Internals // todo: use array instead of memory stream? using (MemoryStream xferredData = new MemoryStream()) { - var xrc = ReturnCode.Success; do { xrc = session.DGImage.ImageMemXfer.Get(xferInfo); @@ -305,7 +354,7 @@ namespace NTwain.Internals } else { - session.SafeSyncableRaiseEvent(new TransferErrorEventArgs(xrc, session.CurrentSource.GetStatus())); + HandleReturnCode(session, xrc); } } } @@ -323,13 +372,15 @@ namespace NTwain.Internals } } + return xrc; } - static void DoImageMemoryFileXfer(ITwainSessionInternal session) + static ReturnCode DoImageMemoryFileXfer(ITwainSessionInternal session) { // since it's memory-file xfer need info from both (maybe) TWSetupMemXfer memInfo; TWSetupFileXfer fileInfo; + ReturnCode xrc = ReturnCode.Failure; if (session.DGControl.SetupMemXfer.Get(out memInfo) == ReturnCode.Success && session.DGControl.SetupFileXfer.Get(out fileInfo) == ReturnCode.Success) { @@ -346,7 +397,7 @@ namespace NTwain.Internals TheMem = PlatformInfo.Current.MemoryManager.Allocate(memInfo.Preferred) }; - var xrc = ReturnCode.Success; + xrc = ReturnCode.Success; using (var outStream = File.OpenWrite(tempFile)) { do @@ -385,7 +436,7 @@ namespace NTwain.Internals } else { - session.SafeSyncableRaiseEvent(new TransferErrorEventArgs(xrc, session.CurrentSource.GetStatus())); + HandleReturnCode(session, xrc); } } catch (Exception ex) @@ -410,6 +461,7 @@ namespace NTwain.Internals DoImageXferredEventRoutine(session, IntPtr.Zero, null, finalFile, fileInfo.Format); } } + return xrc; } static void DoImageXferredEventRoutine(ITwainSessionInternal session, IntPtr dataPtr, byte[] dataArray, string filePath, FileFormat format) diff --git a/src/NTwain/Properties/VersionInfo.cs b/src/NTwain/Properties/VersionInfo.cs index c257785..eb01490 100644 --- a/src/NTwain/Properties/VersionInfo.cs +++ b/src/NTwain/Properties/VersionInfo.cs @@ -23,7 +23,7 @@ namespace NTwain /// /// The build release version number. /// - public const string Build = "3.3.8"; // change this for each nuget release + public const string Build = "3.3.9"; // change this for each nuget release } diff --git a/src/NTwain/TwainSession.cs b/src/NTwain/TwainSession.cs index 55b2de6..806eb61 100644 --- a/src/NTwain/TwainSession.cs +++ b/src/NTwain/TwainSession.cs @@ -202,6 +202,15 @@ namespace NTwain /// public bool IsTransferring { get { return State > 5; } } + /// + /// Whether to stop the transfer process when transfer error is encountered. + /// May be required on some sources. + /// + /// + /// true to stop on transfer error; otherwise, false. + /// + public bool StopOnTransferError { get; set; } + /// /// Opens the data source manager. This must be the first method used /// before using other TWAIN functions. Calls to this must be followed by