This project has moved. For the latest updates, please go here.

A question regarding AcquireError

Jan 2, 2015 at 3:07 PM
Thanks a lot for your Twain library!
I have a question regarding the AcquireError callback.
I created an error condition (the scanner is in power saving mode).
When I scan using the driver UI, I get a message (box) with an error saying that the device is in that mode.
However when trying to scan using Saraff.Twain.dll, I don't get the expected AquireError event.
I did some debugging and I found out that in the Acquire method there is a condition:
if(this._EnableDataSource()) {

In case of my scanner (and the state it is in), this check is false. However there is no code to handle the else branch.

Would it make sense to throw an exception or to call the AcquireError callback?

Thanks in advance,
Michael
Coordinator
Jan 2, 2015 at 7:58 PM
Hello, msbic!
Thank you for your feedback!
I fixed this problem. You can download latest source code of the Saraff.Twain.NET and try it.
Jan 5, 2015 at 3:29 PM
Thanks. It does throw an exception now.
However it does it for the normal case as well.
I wonder if the for loop

for(TwRC _rc=this._dsmEntry.DsInvoke(this.AppId,this._srcds,TwDG.Control,TwDAT.UserInterface,TwMSG.EnableDS,ref _guif); _rc!=TwRC.Success; ) {
                throw new TwainException(this._GetTwainStatus(),_rc);
            }
in the _EnableDataSource has anything to do with that.
Coordinator
Jan 5, 2015 at 6:25 PM
Hello, msbic!
Using cycle necessary to limit the scope of the variable _rc. If the flow of control will fall into a cycle, then more than one iteration, it can not do. You yourself can will see it in the debugger.
Jan 5, 2015 at 7:30 PM
Thanks, I understand now.

For that particular scanner, I can scan with the driver UI without issues. However, when scanning using Saraff.Net, I first get SetupFileXferEvent, and the AcquireErrorEvent. I think that this is an issue with Konica Minolta Twain driver, but I am not 100% certain.

One more issue. First time I try to scan, the message is "It worked!", after that the message is Unknown Error, the error code that I was getting is 0x8015,
which is not handled by _CodeToMessage.
Coordinator
Jan 5, 2015 at 8:06 PM
Write a exception type (ex.GetType().Name), stack trace (ex.StackTrace) and Message (for TwainException write also ConditionCode and ReturnCode). Also write information for all inner exception.
Jan 6, 2015 at 2:12 PM
I cannot reproduce this one for now.

I have another issue. With that Konica Minolta I am getting TwCC.BadProtocol. I get the file successfully.
Do you have an idea when this condition is triggered?
Jan 6, 2015 at 2:39 PM
Back to the previous issue (Exception with It worked! message)

ex.GetType().Name = TwainException
ex.StackTrace = ex.StackTrace " at Saraff.Twain.Twain32._EnableDataSource() in c:\Users.....Saraff.Twain(1)\Saraff.Twain\sources\Saraff.Twain\Twain32.cs:line 262\r\n at Saraff.Twain.Twain32.Acquire() in c:\Users....Saraff.Twain(1)\Saraff.Twain\sources\Saraff.Twain\Twain32.cs:line 279\r\n "

ex.Message = "It worked!"
Coordinator
Jan 6, 2015 at 3:24 PM
Edited Jan 6, 2015 at 3:34 PM
Hello, msbic!
For issue 1 (Exception with It worked! message): what are the values for the variables ex.ReturnCode, ex.ConditionCode , _twain32.ShowUI and _twain32.ModalUI?
For issue 2 (TwCC.BadProtocol): what are the values for the variables ex.ReturnCode and ex.StackTrace?
Jan 6, 2015 at 5:16 PM
Issue 1
ex.ConditionCode = Success
ex.ReturnCode = Failure
_twain32.ShowUI = false
_twain32.ModalUI = false

Issue 2
e.Exception.ReturnCode = Failure
e.Exception.StackTrace = e.Exception.StackTrace " at Saraff.Twain.Twain32._FileTransferPictures() in c:\Users..Twain32.cs:line 1069\r\n at Saraff.Twain.Twain32._TwCallbackProcCore(TwMSG msg, Action`1 endAction) in c:\Users..Twain32.cs:line 1199"
Coordinator
Jan 6, 2015 at 7:01 PM
Issue 1:
Try insert follow line of code before Twain32.Acquire() invoking method:
MessageBox.Show(System.Threading.Thread.CurrentThread.GetApartmentState().ToString(),"Saraff.Twain.Sample2",MessageBoxButtons.OK,MessageBoxIcon.Information);
Issue 2:
TWAIN Session Review (3-24, TWAIN 2.2 Specification)
Image

DG_CONTROL / DAT_SETUPFILEXFER / MSG_GET (7-86, TWAIN 2.2 Specification)
Call: DSM_Entry (pOrigin, pDest, DG_CONTROL, DAT_SETUPFILEXFER,MSG_GET, pSetupFile);
pSetupFile = A pointer to a TW_SETUPFILEXFER structure

Valid States: 4 through 6
Description: Returns information about the file into which the Source has or will put the acquired DG_IMAGE or DG_AUDIO data.
Code of Saraff.Twain.NET (lines 1054-1070)
/* STATE 6 */
for(TwRC _rc=this._dsmEntry.DsInvoke(this.AppId,this._srcds,TwDG.Control,TwDAT.SetupFileXfer,TwMSG.Set,ref _fileXfer); _rc!=TwRC.Success; ) {
    throw new TwainException(this._GetTwainStatus(),_rc);
}

/* BEGIN STATE 7 */
for(TwRC _rc=this._dsmEntry.DsRaw(this.AppId,this._srcds,TwDG.Image,TwDAT.ImageFileXfer,TwMSG.Get,IntPtr.Zero); _rc!=TwRC.XferDone; ) {
    throw new TwainException(this._GetTwainStatus(),_rc);
}
// DG_IMAGE / DAT_IMAGEINFO / MSG_GET
// DG_IMAGE / DAT_EXTIMAGEINFO / MSG_GET
this._OnXferDone(new XferDoneEventArgs(this._GetImageInfo,this._GetExtImageInfo));

for(TwRC _rc=this._dsmEntry.DsInvoke(this.AppId,this._srcds,TwDG.Control,TwDAT.PendingXfers,TwMSG.EndXfer,ref _pxfr); _rc!=TwRC.Success; ) {
    throw new TwainException(this._GetTwainStatus(),_rc);
}
/* END STATE 7 */

/* BEGIN STATE 6 */
for(TwRC _rc=this._dsmEntry.DsInvoke(this.AppId,this._srcds,TwDG.Control,TwDAT.SetupFileXfer,TwMSG.Get,ref _fileXfer); _rc!=TwRC.Success; ) {
    throw new TwainException(this._GetTwainStatus(),_rc); /* THROW EXCEPTION  (TwCC.BadProtocol) */
}
Thus, Saraff.Twain.NET in this case is implemented correctly. The problem to the data source (driver of scanner).
Jan 6, 2015 at 7:50 PM
Thanks!

For issue 1, I get STA.
Coordinator
Jan 7, 2015 at 6:55 AM
Hello, msbic!
For issue 1:
DG_CONTROL / DAT_USERINTERFACE / MSG_ENABLEDS (7-100, TWAIN 2.2 Specification)
Call: 
DSM_Entry(pOrigin, pDest, DG_CONTROL, DAT_USERINTERFACE, MSG_ENABLEDS, pUserInterface);
pUserInterface = A pointer to a TW_USERINTERFACE structure

Valid States: 
4 only (Transitions to State 5, if successful)

Description: 
This operation causes three responses in the Source:
• Places the Source into a “ready to acquire” condition. If the application raises the Source’s user
interface (see #2, below), the Source will wait to assert MSG_XFERREADY until the “GO” button
in its user interface or on the device is clicked. If the application bypasses the Source’s user
interface, this operation causes the Source to become immediately “armed”. That is, the Source
should assert MSG_XFERREADY as soon as it has data to transfer.
• The application can choose to raise the Source’s built-in user interface, or not, using this
operation. The application signals the Source’s user interface should be displayed by setting
pUserInterface->ShowUI to TRUE. If the application does not want the Source’s user interface
to be displayed, or wants to replace the Source’s user interface with one of its own, it sets
pUserInterface->ShowUI to FALSE. If activated, the Source’s user interface will remain
displayed until it is closed by the user or explicitly disabled by the application (see Note).
• Terminates Source’s acceptance of “set capability” requests from the application. Capabilities
can only be negotiated in State 4 (unless special arrangements are made using the
CAP_EXTENDEDCAPS capability). Values of capabilities can still be inquired in States 5 through 7.

Note: Once the Source is enabled, the application must begin sending the Source every event
that enters the application’s main event loop. The application must continue to send the
Source events until it disables (MSG_DISABLEDS) the Source. This is true even if the
application chooses not to use the Source’s built-in user interface.

Application:
Set pUserInterface->ShowUI to TRUE to display the Source’s built-in user interface, or to
FALSE to place the Source in an “armed” condition so that it is immediately prepared to acquire
data for transfer. Set ShowUI to FALSE only if bypassing the Source’s built-in user interface—that
is, only if the application is prepared to handle all user interaction necessary to acquire data from
the selected Source.
Sources are not required to be enabled without showing their User Interface (i.e.
TW_USERINTERFACE.ShowUI = FALSE). If a Source does not support ShowUI = FALSE, they will
continue to be enabled just as if ShowUI = TRUE, but return TWRC_CHECKSTATUS. The
application can check for this Return Code and continue knowing the Source’s User Interface is
being displayed.
Return Codes
TWRC_SUCCESS
TWRC_CHECKSTATUS /* Source cannot enable without User Interface so it enabled with the User Interface.*/
TWRC_FAILURE
    TWCC_BADDEST /* No such Source in-session with application*/
    TWCC_LOWMEMORY /* Not enough memory to open the Source*/
    TWCC_OPERATIONERROR /* Internal Source error; handled by the Source*/
    TWCC_SEQERROR /* Operation invoked in invalid state*/
    TWCC_NOMEDIA /* Source has nothing to capture */
Code of Saraff.Twain.NET (lines 256-263)
TwUserInterface _guif=new TwUserInterface() {
    ShowUI=this.ShowUI,
    ModalUI=this.ModalUI,
    ParentHand=this._hwnd
};
for(TwRC _rc=this._dsmEntry.DsInvoke(this.AppId,this._srcds,TwDG.Control,TwDAT.UserInterface,TwMSG.EnableDS,ref _guif); _rc!=TwRC.Success; ) {
    throw new TwainException(this._GetTwainStatus(),_rc); /* THROW EXCEPTION (TwRC.Failure)*/
}
Thus, if only one thread work with a Saraff.Twain.NET (all calls made from same thread that created the instance of the class Twain32), then the problem is in the data source.
Marked as answer by SARAFF on 1/15/2015 at 10:56 AM