ntwain icon indicating copy to clipboard operation
ntwain copied to clipboard

Clean imprinting settings issue.

Open RaHorusFreak opened this issue 4 months ago • 0 comments

Hello team! I'm using a direct approach for scanning on multithreaded UI environments. Basically, i don't keep a session alive during the programs execution, instead, i create and finalize sessions as i need to scan any document. This is a fragment of the code i'm using:

internal static string Scan(string deviceName, string outPath, string imprintText)
{
    lock(locker)
    {
        bool cancelled = false, end = false;
        Exception exc = null;
        ReturnCode scanResult = ReturnCode.Busy;
        string result = null;
        TwainSession session = null;
        DataSource dataSource = null;
        try
        {
            using(WebdocSupport.Domain.DisposableList<MemoryStream> scannedMemoryStreamImages = new WebdocSupport.Domain.DisposableList<MemoryStream>())
            {
                OpenSessionAndDatasource(deviceName, ts =>
                {
                    ts.TransferCanceled += (s, e) => cancelled = true;
                    ts.TransferError += (s, e) => exc = e.Exception;
                    ts.DataTransferred += (s, e) =>
                    {
                        if(e.NativeData != IntPtr.Zero)
                        {
                            MemoryStream ms = new MemoryStream();
                            e.GetNativeImageStream().CopyTo(ms);
                            ms.Position = 0;
                            scannedMemoryStreamImages.Add(ms);
                        }
                        else if(!string.IsNullOrEmpty(e.FileDataPath))
                            using(FileStream fs = new FileStream(e.FileDataPath, FileMode.Open, FileAccess.Read))
                            {
                                MemoryStream ms = new MemoryStream();
                                fs.CopyTo(ms);
                                ms.Position = 0;
                                scannedMemoryStreamImages.Add(ms);
                            }
                    };
                    ts.SourceDisabled += (s, e) =>
                    {
                        try
                        {
                            if(scanResult == ReturnCode.Success && scannedMemoryStreamImages.Count > 0 && !cancelled && exc == null)
                            {
                                string file = Path.Combine(WDInputController.printFolder, $"{Guid.NewGuid()}.pdf");
                                ...
                                    result = file;
                                }
                            }
                            else if(scannedMemoryStreamImages.Count == 0)
                                cancelled = true;
                        }
                        catch(Exception exception)
                        {
                            exc = exception;
                        }
                    };
                    ts.SourceDisabled += (s, e) => end = true;
                }, out session, out dataSource);
                if(!string.IsNullOrWhiteSpace(imprintText))
                    dataSource._SetImprintSettings(imprintText);
                scanResult = dataSource.Enable(SourceEnableMode.ShowUI, false, IntPtr.Zero);
                SpinWait.SpinUntil(() => end);
                if(exc != null && !cancelled)
                    throw exc;
            }
        }
        finally
        {
            if(dataSource?.IsOpen == true)
            {
                dataSource._CleanImprintSettings();
                dataSource.Close();
            }
            if(session?.IsDsmOpen == true)
                session.Close();
        }
        return result;
    }
}

private static void OpenSessionAndDatasource(string deviceName, Action<TwainSession> ConfigureSession, out TwainSession session, out DataSource dataSource)
        {
            session = null;
            dataSource = null;
            try
            {
                ConfigureSession(session = new TwainSession(TWIdentity.CreateFromAssembly(DataGroups.Image, Assembly.GetExecutingAssembly()))
                {
                    StopOnTransferError = true
                });
                if(session.Open() == ReturnCode.Success)
                {
                    dataSource = session.FirstOrDefault(ds => ds.Name.Equals(deviceName, StringComparison.OrdinalIgnoreCase));
                    if(dataSource?.Open() == ReturnCode.Success)
                        return;
                }
                throw new Exception(AppMessages.message_badScanDevice);
            }
            catch
            {
                if(dataSource?.IsOpen == true)
                    dataSource.Close();
                if(session?.IsDsmOpen == true)
                    session.Close();
                throw;
            }
        }

private static void _CleanImprintSettings(this DataSource dataSource)
        {
            if(dataSource.Capabilities.CapPrinterString.CanSet)
                dataSource.Capabilities.CapPrinterString.SetValue(string.Empty);
            if(dataSource.Capabilities.CapPrinterEnabled.CanSet)
                dataSource.Capabilities.CapPrinterEnabled.SetValue(BoolType.False);
        }

private static void _SetImprintSettings(this DataSource dataSource, string imprintText)
        {
            if(dataSource.Capabilities.CapPrinterEnabled.CanSet)
                dataSource.Capabilities.CapPrinterEnabled.SetValue(BoolType.True);
            if(dataSource.Capabilities.CapPrinter.CanSet)
                dataSource.Capabilities.CapPrinter.SetValue(Printer.ImprinterBottomAfter);
            if(dataSource.Capabilities.CapPrinterMode.CanSet)
                dataSource.Capabilities.CapPrinterMode.SetValue(PrinterMode.SingleString);
            if(dataSource.Capabilities.CapPrinterCharRotation.CanSet)
                dataSource.Capabilities.CapPrinterCharRotation.SetValue(-90);
            if(dataSource.Capabilities.CapPrinterString.CanSet)
                dataSource.Capabilities.CapPrinterString.SetValue(imprintText);
        }

As you can see, i use _CleanImprintSettings for releasing the imprinter settings after scanning a doc. Is my approach of changing settings after scannig a document right? Because sometimes when i try to scan a doc outside my app, the last imprinted text stills there. Also sometimes the app crashes without any catchable exception (i think is due to the multithreaded UI forms approach, or for calling _CleanImprintSettings after scanning...). Thanks in advance. Best regards.

PD: My app is x86 without changes on session.SynchronizationContext, NTwain.PlatformInfo.Current.PreferNewDSM or custom MessageLoop.

RaHorusFreak avatar Oct 28 '24 02:10 RaHorusFreak