Should now catch error before first transfer and during transfer loop as a possible #57 fix.

This commit is contained in:
Eugene Wang 2016-02-20 06:50:11 -05:00
parent 870ecd64a4
commit b603dd7f59
4 changed files with 143 additions and 73 deletions

View File

@ -85,6 +85,15 @@ namespace NTwain
/// </summary> /// </summary>
bool IsTransferring { get; } bool IsTransferring { get; }
/// <summary>
/// Whether to stop the transfer process when transfer error is encountered.
/// May be required on some sources.
/// </summary>
/// <value>
/// <c>true</c> to stop on transfer error; otherwise, <c>false</c>.
/// </value>
bool StopOnTransferError { get; set; }
/// <summary> /// <summary>
/// Try to show the built-in source selector dialog and return the selected source. /// Try to show the built-in source selector dialog and return the selected source.
/// This is not recommended and is only included for completeness. /// This is not recommended and is only included for completeness.

View File

@ -45,63 +45,89 @@ namespace NTwain.Internals
var pending = new TWPendingXfers(); var pending = new TWPendingXfers();
var rc = session.DGControl.PendingXfers.Get(pending); var rc = session.DGControl.PendingXfers.Get(pending);
do if (rc == ReturnCode.Success)
{ {
#region raise xfer ready do
var preXferArgs = new TransferReadyEventArgs(session.CurrentSource, pending.Count, pending.EndOfJob); ;
session.SafeSyncableRaiseEvent(preXferArgs);
#endregion
#region actually handle xfer
if (preXferArgs.CancelAll)
{ {
rc = session.DGControl.PendingXfers.Reset(pending); #region raise xfer ready
}
else var preXferArgs = new TransferReadyEventArgs(session.CurrentSource, pending.Count, pending.EndOfJob); ;
{ session.SafeSyncableRaiseEvent(preXferArgs);
if (!preXferArgs.CancelCurrent)
#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: switch (imgXferMech)
DoImageMemoryXfer(session); {
break; case XferMech.Memory:
case XferMech.File: rc = DoImageMemoryXfer(session);
DoImageFileXfer(session); break;
break; case XferMech.File:
case XferMech.MemFile: rc = DoImageFileXfer(session);
DoImageMemoryFileXfer(session); break;
break; case XferMech.MemFile:
case XferMech.Native: rc = DoImageMemoryFileXfer(session);
default: // always assume native break;
DoImageNativeXfer(session); case XferMech.Native:
break; 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 ReturnCode.Cancel:
{ default:
case XferMech.File: // as usual
DoAudioFileXfer(session); rc = session.DGControl.PendingXfers.EndXfer(pending);
break; break;
case XferMech.Native: }
default: // always assume native
DoAudioNativeXfer(session); if (rc != ReturnCode.Success && session.StopOnTransferError)
break; {
} // 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. // 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 // 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 #region audio xfers
static void DoAudioNativeXfer(ITwainSessionInternal session) static ReturnCode DoAudioNativeXfer(ITwainSessionInternal session)
{ {
IntPtr dataPtr = IntPtr.Zero; IntPtr dataPtr = IntPtr.Zero;
IntPtr lockedPtr = IntPtr.Zero; IntPtr lockedPtr = IntPtr.Zero;
ReturnCode xrc = ReturnCode.Failure;
try try
{ {
var xrc = session.DGAudio.AudioNativeXfer.Get(ref dataPtr); xrc = session.DGAudio.AudioNativeXfer.Get(ref dataPtr);
if (xrc == ReturnCode.XferDone) if (xrc == ReturnCode.XferDone)
{ {
session.ChangeState(7, true); session.ChangeState(7, true);
@ -133,7 +176,7 @@ namespace NTwain.Internals
} }
else else
{ {
session.SafeSyncableRaiseEvent(new TransferErrorEventArgs(xrc, session.CurrentSource.GetStatus())); HandleReturnCode(session, xrc);
} }
} }
catch (Exception ex) catch (Exception ex)
@ -156,39 +199,43 @@ namespace NTwain.Internals
dataPtr = IntPtr.Zero; dataPtr = IntPtr.Zero;
} }
} }
return xrc;
} }
static void DoAudioFileXfer(ITwainSessionInternal session) static ReturnCode DoAudioFileXfer(ITwainSessionInternal session)
{ {
string filePath = null; string filePath = null;
TWSetupFileXfer setupInfo; 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; filePath = setupInfo.FileName;
}
var xrc = session.DGAudio.AudioFileXfer.Get(); xrc = session.DGAudio.AudioFileXfer.Get();
if (xrc == ReturnCode.XferDone) if (xrc == ReturnCode.XferDone)
{ {
session.SafeSyncableRaiseEvent(new DataTransferredEventArgs(session.CurrentSource, filePath, (FileFormat)0)); session.SafeSyncableRaiseEvent(new DataTransferredEventArgs(session.CurrentSource, filePath, (FileFormat)0));
} }
else else
{ {
session.SafeSyncableRaiseEvent(new TransferErrorEventArgs(xrc, session.CurrentSource.GetStatus())); HandleReturnCode(session, xrc);
}
} }
return xrc;
} }
#endregion #endregion
#region image xfers #region image xfers
static void DoImageNativeXfer(ITwainSessionInternal session) static ReturnCode DoImageNativeXfer(ITwainSessionInternal session)
{ {
IntPtr dataPtr = IntPtr.Zero; IntPtr dataPtr = IntPtr.Zero;
IntPtr lockedPtr = IntPtr.Zero; IntPtr lockedPtr = IntPtr.Zero;
ReturnCode xrc = ReturnCode.Failure;
try try
{ {
var xrc = session.DGImage.ImageNativeXfer.Get(ref dataPtr); xrc = session.DGImage.ImageNativeXfer.Get(ref dataPtr);
if (xrc == ReturnCode.XferDone) if (xrc == ReturnCode.XferDone)
{ {
session.ChangeState(7, true); session.ChangeState(7, true);
@ -200,7 +247,7 @@ namespace NTwain.Internals
} }
else else
{ {
session.SafeSyncableRaiseEvent(new TransferErrorEventArgs(xrc, session.CurrentSource.GetStatus())); HandleReturnCode(session, xrc);
} }
} }
catch (Exception ex) catch (Exception ex)
@ -223,9 +270,10 @@ namespace NTwain.Internals
dataPtr = IntPtr.Zero; dataPtr = IntPtr.Zero;
} }
} }
return xrc;
} }
static void DoImageFileXfer(ITwainSessionInternal session) static ReturnCode DoImageFileXfer(ITwainSessionInternal session)
{ {
string filePath = null; string filePath = null;
TWSetupFileXfer setupInfo; TWSetupFileXfer setupInfo;
@ -241,14 +289,16 @@ namespace NTwain.Internals
} }
else 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; 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(); TWImageMemXfer xferInfo = new TWImageMemXfer();
try try
@ -269,7 +319,6 @@ namespace NTwain.Internals
// todo: use array instead of memory stream? // todo: use array instead of memory stream?
using (MemoryStream xferredData = new MemoryStream()) using (MemoryStream xferredData = new MemoryStream())
{ {
var xrc = ReturnCode.Success;
do do
{ {
xrc = session.DGImage.ImageMemXfer.Get(xferInfo); xrc = session.DGImage.ImageMemXfer.Get(xferInfo);
@ -305,7 +354,7 @@ namespace NTwain.Internals
} }
else 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) // since it's memory-file xfer need info from both (maybe)
TWSetupMemXfer memInfo; TWSetupMemXfer memInfo;
TWSetupFileXfer fileInfo; TWSetupFileXfer fileInfo;
ReturnCode xrc = ReturnCode.Failure;
if (session.DGControl.SetupMemXfer.Get(out memInfo) == ReturnCode.Success && if (session.DGControl.SetupMemXfer.Get(out memInfo) == ReturnCode.Success &&
session.DGControl.SetupFileXfer.Get(out fileInfo) == ReturnCode.Success) session.DGControl.SetupFileXfer.Get(out fileInfo) == ReturnCode.Success)
{ {
@ -346,7 +397,7 @@ namespace NTwain.Internals
TheMem = PlatformInfo.Current.MemoryManager.Allocate(memInfo.Preferred) TheMem = PlatformInfo.Current.MemoryManager.Allocate(memInfo.Preferred)
}; };
var xrc = ReturnCode.Success; xrc = ReturnCode.Success;
using (var outStream = File.OpenWrite(tempFile)) using (var outStream = File.OpenWrite(tempFile))
{ {
do do
@ -385,7 +436,7 @@ namespace NTwain.Internals
} }
else else
{ {
session.SafeSyncableRaiseEvent(new TransferErrorEventArgs(xrc, session.CurrentSource.GetStatus())); HandleReturnCode(session, xrc);
} }
} }
catch (Exception ex) catch (Exception ex)
@ -410,6 +461,7 @@ namespace NTwain.Internals
DoImageXferredEventRoutine(session, IntPtr.Zero, null, finalFile, fileInfo.Format); DoImageXferredEventRoutine(session, IntPtr.Zero, null, finalFile, fileInfo.Format);
} }
} }
return xrc;
} }
static void DoImageXferredEventRoutine(ITwainSessionInternal session, IntPtr dataPtr, byte[] dataArray, string filePath, FileFormat format) static void DoImageXferredEventRoutine(ITwainSessionInternal session, IntPtr dataPtr, byte[] dataArray, string filePath, FileFormat format)

View File

@ -23,7 +23,7 @@ namespace NTwain
/// <summary> /// <summary>
/// The build release version number. /// The build release version number.
/// </summary> /// </summary>
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
} }

View File

@ -202,6 +202,15 @@ namespace NTwain
/// </summary> /// </summary>
public bool IsTransferring { get { return State > 5; } } public bool IsTransferring { get { return State > 5; } }
/// <summary>
/// Whether to stop the transfer process when transfer error is encountered.
/// May be required on some sources.
/// </summary>
/// <value>
/// <c>true</c> to stop on transfer error; otherwise, <c>false</c>.
/// </value>
public bool StopOnTransferError { get; set; }
/// <summary> /// <summary>
/// Opens the data source manager. This must be the first method used /// Opens the data source manager. This must be the first method used
/// before using other TWAIN functions. Calls to this must be followed by /// before using other TWAIN functions. Calls to this must be followed by