dynarithmic / twain_library

Dynarithmic TWAIN Library, Version 5.x
Apache License 2.0
60 stars 25 forks source link

DTWAIN_SelectSource() fails #33

Closed sean-neeley closed 2 years ago

sean-neeley commented 2 years ago

We wrote an app with DTWAIN and have a user trying to use a Canon DR-M260 scanner. The DTWAIN_SelectSource() function brings up the dialog where he can select his scanner. It is listed as "Canon DR-M200 TWAIN". After selecting the scanner and hitting SELECT, the error -1002 is returned and DTWAIN_GetErrorString() returns "Invalid DTWAIN_SOURCE".

The C# code is basically:

                DTWAIN_SOURCE newSource = TwainAPI.DTWAIN_SelectSource();
                if (newSource.Equals(IntPtr.Zero))
                {
                    int error = TwainAPI.DTWAIN_GetLastError();
                    if (error != 0)
                    {
                        if (error == TwainAPI.DTWAIN_ERR_SOURCESELECTION_CANCELED)
                        {
                            return true;
                        }
                        // User did not cancel. There is a real problem.
                        StringBuilder sbError = new StringBuilder(256);
                        TwainAPI.DTWAIN_GetErrorString(error, sbError, sbError.Capacity);
                        string sErr = $"Error {error}: {sbError.ToString()}";
                        Logger.WriteLine(sErr);
                        MessageBox.Show(sErr, "Source Selection Failed");
                    }
                }

What could cause this issue? Are there any troubleshooting ideas you can suggest? We had the user try another TWAIN scan application, IrfanView and they were able to select a source in that application and scan a page in that application.

image006 (1)

unnamed

Thank you

dynarithmic commented 2 years ago

1) Did you try the DTWDEMO.exe program?
2) Please produce a log of the functions (DTWAIN_SetTwainLog). 3) Is this a 32-bit or 64-bit application/driver? Possibly you are running a 64-bit application, while IrfanView is running as 32-bit, or vice-versa. The bitness of your application determines the scanner driver that is being used.

dynarithmic commented 2 years ago

Also, if you are able to (i.e. you use Visual Studio), the error can be debugged if you go to the source_repo, the master branch, and use the appropriate debug version of the DTWAIN dll (dtwain32ud.dll, dtwain32d.dll, dtwain64ud.dll, dtwain64d.dll) and see where DTWAIN detects the invalid source. You would also need your C# code to use a cs that matches one of the mentioned debug dlls.

Then you can load the appropriate Visual Studio project into Visual Studio (you need VS 2015 and above), run your C# program, and attach to it using the Visual Studio debug menu. You can put a breakpoint in the DTWAIN_OpenSource() function and see where it takes you (it should be in ctlsourceopen.cpp). At some point, you will see the -1002 error being discovered.

sean-neeley commented 2 years ago

Thanks, I'm working with our client to try these things. Our app is 64bit. I instructed the user to install the 64bit version of IrfanView and gave them the link to the 64bit download page, so I'm assuming that is what they downloaded and installed, although I can't be 100% sure without logging into their workstation remotely. I'll let you know what I find.

dynarithmic commented 2 years ago

The issue can almost always be determined by creating a log file (DTWAIN_SetTwainLog, and log everything to a file). Then the call(s) to the TWAIN subsystem are collected. In the file, you will see the "call stack", nicely indented, and also the calls to the Twain DSM and their return statuses.

Unfortunately, I don't have this model of the Canon scanner. So right now, all that I would have is a log file. If you have access to the scanner, you could debug the issue by following the steps I outlined in the previous message, and if you know C++ well enough, make a coding change and report the issue. It has been done before by a couple of users.

The somewhat good news is that at some point DTWAIN did detect something was amiss, and returned the -1002 error. If DTWAIN returned no error and later on things went awry, or outright crashed your program when attempting to open the source, then that would be a bigger problem.

sean-neeley commented 2 years ago

DTWAIN_good.log DTWAIN_bad.log

Ok, I was never able to get a log from the Canon DR-M260, but the same issue came up with an HP 7000 S3 scanner. I got a log from the client workstation (DTWAIN_bad.log) and was able to generate a log of a successful source selection from our own test workstation using the same scanner model (DTWAIN_good.log), for comparison. What I notice is that DSM_Entry() with MSG_OPENDS is called and returns a 3. It shows it as TWRC_CANCEL, but I don't think that is a valid return value. I believe MSG_OPENDS should return a TWCC_xxxxx error. You are more familiar with the logging... can you spot anything wrong in the log? Thank you.

dynarithmic commented 2 years ago

I looked at the bad log, and it indeed returns a TWRC_CANCEL for the triplet DG_CONTROL/DAT_IDENTITY/MSG_OPENDS. If you have a copy of the TWAIN 2.4 specification, Chapter 7 (page 7-66), are the return codes the source gives for failure. TWRC_CANCEL is not one of them. I am wondering if there is an issue with the TWAIN Data Source Manager for the 64-bit drivers on the client machine. Having two different scanners have the same issue is highly suspicious.

Also, since the error occurs almost immediately, something very basic seems to be wrong or corrupted. The selection of the source is successful, however opening the selected source is where the error is occurring.

The DSM is the file TWAINDSM.DLL. You can get the latest here. Maybe check the date of the file you're using as opposed to the customer file. You can get the location of the DSM in use by calling DTWAIN_GetActiveDSMPath to get the path of the data source manager.

Another thing you can do is after DTWAIN_SysInitialize, you can separate the selecting and opening of the TWAIN sources by calling DTWAIN_OpenSourcesOnSelect, and give it a 0 as the argument.

What this will do is when a source is selected, your application has to manually call DTWAIN_OpenSource() after the source has been selected, or you have to make the low-level TWAIN call yourself using the appropriate TWAIN triplet (see the log for the triplet to use, plus investigate the usage of DTWAIN_CallDSMProc, which allows your application to make the TWAIN call).

dynarithmic commented 2 years ago

As a heads up, the 2.x version of the TWAIN DSM (TWAINDSM.DLL) is open source (it is located at the same (or roughly the same) URL link I mentioned in the previous comment.

So you could debug everything (except for the scanner driver), even further. There is a spot in the DSM code where all the TWAIN triplets get processed, and there you could put a breakpoint for the DG_CONTROL/DAT_IDENTITY/MSG_OPENDS triplet as it comes in from DTWAIN .

However the issue is that only the client's machine is producing this error, so somehow you would need to get access to that machine to debug the DSM. What you could try to do is

1) Rebuild TWAINDSM.DLL, give it to the client and retest 2) Have the client use a different computer and see if the problem happens there.

sean-neeley commented 2 years ago

Thanks, that is all very helpful info. We were packaging TWAINDSM.DLL version 2.1.2.0 with our app. I have changed it to use TWAINDSM.DLL 2.4.0.0 and will see if that helps. If not, I'll try the other suggested code changes and building my own debug version of TWAINDSM.DLL. I will let you know what I find.

sean-neeley commented 2 years ago

OK, after 3 weeks I finally got a DTWAIN log from the person trying to use the Canon DR-M260. This was using the TWAINDSM.DLL version 2.4.0.0 that you gave me. I'm attaching the log. DTWAIN.log

dynarithmic commented 2 years ago

The new log shows this when attempting to open the source when getting the status of the open failure:

TWCC_OPERATIONERROR

This error is one of the errors that the MSG_OPENDS triplet can return. On chapter-page 7-66 of the 2.4 specification, this is the information:

TWCC_OPERATIONERROR   /* internal Source error;*/
                                           /* handled by the Source */

I focused on the returned source handle from the call to DTWAIN_SelectSource, and it is indeed the same handle used for DTWAIN_OpenSource, which effectively rules out whether DTWAIN is sending DTWAIN_OpenSource the right handle. This is confirmed in the log, since for the TWAIN triplet

DG_CONTROL/DAT_IDENTITY/MSG_OPENDS

The TW_MEMREF is the information on the data source to open (the TW_IDENTITY). If you go to the Twain specification 2.4 documentation, and chapter-page 7-66, you see the triplet described.

The only thing I can suggest at this point is that the DSM is not installed correctly or misconfigured on the client, or some other issue. Debugging the 2.4 DSM may be the only option at this point, to see why the status is set to TWCC_OPERATIONERROR.

sean-neeley commented 2 years ago

I'm looking over the TWAIN_DSM source and it looks like you can set an environment variable to get a log file. I'm going to start with that and try to get a log before I figure out how to compile and debug it.

set TWAINDSM_LOG=C:\path\TWAINDSM.log

Also the link you gave me for TWAINDSM.dll was for 2.4.0.0 from 5 years ago. Looks like there is an even newer version, 2.4.3.0 from 17 months ago. I'll try using it. link

sean-neeley commented 2 years ago

OK, I got a TWAINDSM log from the workstation with the HP scanner that is having this issue. This workstation was working OK at one point and now the MSG_OPENDS call returns a failure every time. In the application, an HP dialog appears showing "The HP imaging device was not found". We checked that the scanner is on and connected and rebooted the workstation several times. I'm not seeing a lot in the log, just 'MSG_OPENDS failed...'. I'm attaching the log.

image001

TWAINDSM (2).log

dynarithmic commented 2 years ago

I think the only thing that can be done at this point is to debug why the failure occurs within the TWAIN DSM itself.

If not that, go to the source code of TWAINDSM and figure out how the DG_CONTROL/DAT_IDENTITY/MSG_OPENDS triplet is processed, and see if there is code that returns MSG_OPENDS on failure.

sean-neeley commented 2 years ago

OK, The HP scanner user wiped the computer and reinstalled windows and everything is working again. Our user with the Canon scanner has pretty much given up testing for us, so I can't get anywhere with that one. We are looking to rework some of our code after your feedback and after reading the TWAIN docs, which we hope will keep the software from getting in this state. Since I don't think the issue is with DTWAIN itself, you can go ahead and close this out. I appreciate the help.

dynarithmic commented 2 years ago

OK, Thanks.

I will close the ticket, but just to add my thoughts on this:

It does seem like it's a driver issue or similar, such as a corrupted TWAIN installation. The code here is more than likely where the issue is, but your log doesn't show any log of the actual error, as suggested by the code in apps.cpp. Note that for every error, something is logged. A debugging session would get to the bottom of what is going on by putting a breakpoint on line 1649 and follow what happens.

This looks almost as-if an exception was thrown after loading the hp driver (after line 1649), and thus the call stack unwound itself back up to dsm.cpp, skipping over all of the code we see in apps.cpp that carefully checks for error conditions.

Anyway, thanks for the information.