dynarithmic / twain_library

Dynarithmic TWAIN Library, Version 5.x
Apache License 2.0
56 stars 24 forks source link

DTWAIN_IsDeviceOnLine always return 0 update version 5.4.3 #94

Open hebo1982 opened 2 months ago

hebo1982 commented 2 months ago

I updated dtwain32u.dll 5.2.0.9 -> the last version 5.4.3. DTWAIN_IsDeviceOnLine always return 0. And I rollback 5.2.0.9 work well.

Code like this, I want to check the device is ready.

if (sourceId != IntPtr.Zero)
{

  var s = TwainAPI.DTWAIN_IsDeviceOnLine(sourceId);

  if (s == 0) sourceId = IntPtr.Zero;
 // 5.4.3 always return 0
}
dynarithmic commented 2 months ago

1) Please specify the device make and model.

2) Please generate a full TWAIN log (DTWAIN_SetTwainLog) to see what is happening when the call is made to the TWAIN system. I cannot use your C# code for verification -- the only thing I can observe is to look at the actual log of the call using a call log.

3) I did a small C++ test using both the sample TWAIN driver and a Plustek 286 SmartOffice scanner using DTWAIN version 5.4.3. Both devices return true (1) for DTWAIN_IsDeviceOnLine, so I am not able to duplicate your error at the API level. Maybe there is an issue with the C# code.

4) As a test, try TwainAPI.DTWAIN_GetCapValues and use the DTWAIN_CV_CAPDEVICEONLINE as the capability value, and DTWAIN_CAPGET as the operation to use. The DTWAIN_IsCapDeviceOnLine function uses DTWAIN_CAPGETCURRENT as the operation, not DTWAIN_CAPGET, so see if this is the issue.

You will need to use the DTWAIN_ArrayGetAtLong(array, 0, int) to determine the actual value in the returned array (the last parameter of the DTWAIN_GetCapValues call, which is filled in by DTWAIN on return of DTWAIN_GetCapValues). So it would look like:

DTWAIN_ARRAY arr;
int success = DTWAIN_GetCapValues(sourceId, TwainAPI.DTWAIN_CV_CAPDEVICEONLINE, DTWAIN_CAPGET, arr);
int retVal = 0;
if (success == 1)
    DTWAIN_ArrayGetAtLong(arr, 0, retVal);
hebo1982 commented 2 months ago

@dynarithmic

thanks for you reply. I recreate this different return value.

using System;
using Dynarithmic;
using Nito.AsyncEx;

namespace ConsoleApplication1
{
    internal class Program
    {
        private static readonly AsyncContextThread asyncContextThread = new AsyncContextThread();
        private static IntPtr sourceId;

        private static R Post<R>(Func<R> callback)
        {
            var r = default(R);
            asyncContextThread.Factory.Run(() => r = callback()).Wait();
            return r;
        }

        public static void Main(string[] args)
        {
            Post(() =>
            {
                var status = TwainAPI.DTWAIN_SysInitialize();

                // TwainAPI.DTWAIN_EndTwainSession();
                TwainAPI.DTWAIN_StartThread(status);

                sourceId = TwainAPI.DTWAIN_SelectSource();

                var isDeviceOnLine = TwainAPI.DTWAIN_IsDeviceOnLine(sourceId);

                Console.WriteLine("sourceId:" + sourceId + ", isDeviceOnLine:" + isDeviceOnLine); // return 1 

                return 0;
            });

            var mainThreadOL = TwainAPI.DTWAIN_IsDeviceOnLine(sourceId);

            // different thread call DTWAIN_IsDeviceOnLine
            // in 5.2.9 == 1 
            // in 5.4.3 == 0
            Console.WriteLine("sourceId:" + sourceId + ", mainThreadOL:" + mainThreadOL);
        }
    }
}

Nito.AsyncEx, make a worker thread for do scanner operation (like my work is desktop app, do scan not on main thread). Sometime I check the scanner is ready with "DTWAIN_IsDeviceOnLine".

I changed my code for support 5.4.3.

Post(()=> {
return TwainAPI.DTWAIN_IsDeviceOnLine(sourceId);
})
dynarithmic commented 2 months ago

You will still need to generate a TWAIN log to determine how your device is handling the TWAIN calls.