dynarithmic / twain_library

Dynarithmic TWAIN Library, Version 5.x
Apache License 2.0
66 stars 26 forks source link

The DTWAIN_AcquireFile method occasionally returns false #129

Open dongshaoyang opened 1 month ago

dongshaoyang commented 1 month ago

When I call DTWAIN_AcquireFile, sometimes it fails to acquire. Here is the log,The issue might occur at line 36034. dtwain.log

I'm not sure what the cause of the problem is, but I noticed that the thread ID changes at line 36032. I'm not certain if this is what's causing the issue.

dongshaoyang commented 1 month ago

dtwain5.log

In this log, the thread ID remains unchanged, yet acquisition still fails. Starting from line 39864, the device selection begins, and at line 40504, opening the data source fails.

Thank you!

dynarithmic commented 1 month ago

What computer language are you using? The log shows different thread ID's being used, and using DTWAIN across threads during one TWAIN session is not guaranteed to work, since TWAIN itself is not thread aware.

In dtwain.log, at the very end of the log, the call to DTWAIN_AcquireFile probably returns 0 due to VerifyHandles sees that the current thread (16868) does not match the thread you initially opened the session with (15032).

I tried to simulate your scenario using a very simple C++ program that calls DTWAIN_SysInitialize(), DTWAIN_AcquireFile(), DTWAIN_SysDestroy(), in a loop. I could not duplicate your issue using C++. So my initial suspicion is that you are using a language or environment that spawns multiple threads and DTWAIN is getting "confused" (let alone TWAIN itself).

If this is the case, it would be safer (if possible) to unload the entire DTWAIN.DLL from memory and reload it again for each time you are calling DTWAIN. This way, the process attaches itself to a brand new instance of the DLL.

dynarithmic commented 1 month ago

For dtwain5.log, there is a TWCC_NODS error when attempting to open the KODAK Scanner: E1xxx. The TWCC_NODS is a TWAIN error to basically mean " Source Manager unable to find the specified Source." (this is mentioned in the TWAIN 2.5 specification).

As to this issue and the one with dtwain.log, can you run the DTWDEMO32U.exe program with no issues? There are options to specify the source by name or select dialog.

Also, if a DTWAIN function returns false, your code should call DTWAIN_GetLastError to get the error code.

If the returned error code is DTWAIN_ERR_BAD_HANDLE, which is -1001, this looks like the issue that dtwain.log is suggesting is one of threading and calling Twain on different threads during one Twain session (or similar). Since I was not able to duplicate your issue, that's the only conclusion as of now that I can come up with.

Note that if the DLL handle is invalid, the logging will also not work on that thread, since all of the DTWAIN logging functions require a valid DTWAIN_HANDLE to be utilized. So the reporting of the DTWAIN_ERR_BAD_HANDLE error cannot be done by the logs, but only through calling DTWAIN_GetLastError and inspecting the value.

dynarithmic commented 1 month ago

Also, see Multithreading Issues. Please read the links to functions such as DTWAIN_StartThread.

dongshaoyang commented 1 month ago

I am using Golang, and the reason for DTWAIN calls appearing on different threads may be due to Golang's scheduling mechanism. I'll try to deal with that.

dtwain-20241029-1.txt Here is today’s log, and the issue still persists. First, I called MysherCameraTwain, and acquisition was successful. After completion, I attempted to switch the device to KODAK, but acquisition failed(line 23615). Following this sequence in the DTWDEMO32U.exe program does not cause any issues.

Error code: -2500, error message: "Could not open TWAIN source - 'KODAK Scanner: E1xxx'". I don't understand why this error occurs.

Thank you!

dynarithmic commented 1 month ago

If the source is opened successfully using DTWDEMO32U.exe, then there is an issue that I cannot resolve with any certainty.

According to the log, the Kodak scanner is selected successfully. Note that selecting a device and opening the device are two separate steps. If the device can be selected but not opened, this indicates that there is something wrong occurring in the way the environment is communicating with the actual hardware.

Selecting a source by itself establishes that TWAIN has found the device's data source, and successfully queried it to establish a TWAIN identifier to associate with it (according to the log, the identifier is found in the TW_MEMREF starting at line 23658 of the log, which is Id=1292).

Opening the source (which is the second step) requires that the device actually is working properly and can be communicated with. If there is an error in opening the source, then something in your environment is preventing this step from occurring.

1) What if you attempted to open the Kodak scanner first? Does it open successfully?

2) If step 1) works correctly, what if you reversed the selection in your tests, i.e. select the Kodak scanner first, and then the MysherCameraTwain second? Does the MysherCameraTwain device open successfully?

dongshaoyang commented 1 month ago
  1. I tried unload the entire DTWAIN.DLL from memory and reload it again for each time. The problem still persists.

  2. It's successfully open the KODAK scanner first, then open MysherCameraTwain. However, when I try to open the KODAK scanner again, the issue occurs. I also tried restart the KODAK scanner, but it was still ineffective. If I want to use KODAK, I can only continue after restarting my application.

This issue is intermittent and does not occur every time.

This may not be a problem with DTWAIN,but I have no idea how to pinpoint the issue.

dynarithmic commented 1 month ago

When you use DTWDEMO32U.exe, can you do multiple scans with the Kodak scanner? More specifically,

1) Open the Kodak scanner using the Twain select source dialog. 2) Scan one or more pages from the document feeder. 2) close the Kodak scanner user interface, 3) choose "Close Source" from the main menu to close out the Kodak source. 4) Select the Kodak source again from the "Select Source" dialog.

and repeat steps 2 to 5 multiple times without issues?

Also, is the Kodak model the "Alaris E1035"? I can possibly get this model to test (no guarantee that I can get this scanner), but need to make sure that the steps outlined above also fail (similar to your current application).

but I have no idea how to pinpoint the issue.

Also, can you try the 32-bit TWAINDSM.DLL found here instead of the default TWAIN_32.DLL? You use this by calling DTWAIN_SetTwainDSM and setting the parameter to DTWAIN_TWAINDSM_VERSION2 before you call DTWAIN_StartTwainSession() (or if you are not calling this function directly, before you open a TWAIN source).

The TWAINDSM.DLL is open source and comes with full source code. This will allow you to debug what is going on when the DG_CONTROL / DAT_IDENTITY / MSG_OPENDS triplet is sent to the TWAIN source manager when attempting to open the Kodak scanner (you can see this call in the logs you sent). It is at that point where everything takes place in getting the scanner to open successfully.

Other than that, the only source code that would be "missing" is the Kodak driver source code, and I doubt that is available to anyone except Kodak.

dongshaoyang commented 1 month ago

Following the steps you mentioned, I used DTWDEMO32U.exe to scan with the KODAK scanner ten times without any issues. Then, I used MysherCameraTwain to scan ten times, which also worked fine. Finally, I switched back to the KODAK scanner, and there were still no issues.

I am using the KODAK E1040 scanner.

I tried using TWAINDSM.DLL, but the problem still persists.

I don't have much knowledge about TWAIN, and I might need to spend some time learning about it.

Thank you!

dongshaoyang commented 1 month ago

When I select the device name "KODAK Scanner: E1xxx," I get the message: -2500 Could not open TWAIN source - "KODAK Scanner: E1xxx." However, when I select "WIA-KODAK E1040 Scanner," I can perform the scan successfully.

dynarithmic commented 1 month ago

This looks like an issue with the Kodak TWAIN driver itself. The WIA driver is actually a WIA bridge to TWAIN that is provided by Microsoft. Usually there are issues with WIA, but in your case, the WIA driver is working, but not the "pure" TWAIN driver provided by Kodak (at least in your Go environment).

Since you did not have an issue with DTWDEMO32U, the only conclusion I can come up with is that the Kodak driver does not behave correctly when encountering an environment that spawns threads.

If you are using the "Select Source" dialog, what you can do is exclude the bad driver from the Select Source dialog by creating your own dialog and filtering out the name when displaying the list of available sources, or use the undocumented DTWAIN_SelectSource2Ex function:

DTWAIN_SOURCE DLLENTRY_DEF DTWAIN_SelectSource2Ex(HWND hWndParent,
                                                  LPCTSTR szTitle,
                                                  LONG xPos,
                                                  LONG yPos,
                                                  LPCTSTR szIncludeFilter,
                                                  LPCTSTR szExcludeFilter,
                                                  LPCTSTR szNameMapping,
                                                  LONG nOptions)

The szExcludeFilter would be a string that consists of the product name "Kodak Scanner: E1xxx". The szIncludeFilter would be NULL, and the szNameMapping would be NULL. Otherwise this function works the same as DTWAIN_SelectSource2.