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